<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Avil Page</title><link>https://avilpage.com/</link><description>Avil Page - Personal &amp; tech blog by Pandikunta Anand Reddy (aka Chillar Anand)</description><atom:link href="https://avilpage.com/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Fri, 25 Sep 2026 10:35:56 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Moving from RayCast to TinyCast</title><link>https://avilpage.com/2026/09/raycast-open-source-tinycast.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I have been &lt;a href="https://avilpage.com/2025/06/raycast-replaced-10-macos-apps.html"&gt;using RayCast&lt;/a&gt; from ~4 years. I built 2 extensions, ~20 custom scripts, contributed to existing extensions. &lt;/p&gt;
&lt;p&gt;I raised support tickets related to automating RayCast exports &amp;amp; settings. Unfortunately, there was no good resolution.&lt;/p&gt;
&lt;h4&gt;FOSS Alternatives&lt;/h4&gt;
&lt;p&gt;When looking at open source alternatives I stumbled on &lt;a href="https://github.com/vicinaehq/vicinae"&gt;Vicinae&lt;/a&gt;, &lt;a href="https://github.com/MystikoLab/rustcast"&gt;RustCast&lt;/a&gt; long back but they were not drop in replacements.&lt;/p&gt;
&lt;p&gt;&lt;img alt="raycast-drop-in-replacement" src="https://avilpage.com/images/tinycast-raycast-open-source-alt.png"&gt;&lt;/p&gt;
&lt;p&gt;Recently &lt;a href="https://github.com/abue-ammar/tinycast"&gt;TinyCast&lt;/a&gt; came out and I am using it as a primary launcher on one of the Mac. It is working well as a drop-in replacement so far without any major issues.&lt;/p&gt;
&lt;p&gt;It is just ~6MB app and consumes only a fraction of CPU/Memory compared to other tools.&lt;/p&gt;
&lt;h4&gt;Software as Moat&lt;/h4&gt;
&lt;p&gt;With AI, it is getting easy to build &amp;amp; customise software. There is a growing trend where users are shifting towards open source alternatives(since I am in FOSS space, I might be biased).&lt;/p&gt;
&lt;p&gt;If you think software only is a moat, it is time to re-think again!&lt;/p&gt;</description><category>macbook</category><category>raycast</category><guid>https://avilpage.com/2026/09/raycast-open-source-tinycast.html</guid><pubDate>Sat, 19 Sep 2026 09:33:06 GMT</pubDate></item><item><title>How I run LLMs locally on Mac</title><link>https://avilpage.com/2026/08/how-i-run-llms-locally-on-mac.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img alt="Harness, Server, and Models" src="https://avilpage.com/images/mac-local-llms.svg"&gt;&lt;/p&gt;
&lt;h4&gt;Harness&lt;/h4&gt;
&lt;p&gt;OpenCode &amp;amp; oh-my-pi come with batteries included and works out of the box.&lt;/p&gt;
&lt;p&gt;Pi is barebones &amp;amp; lightweight. 
There are quality plugins available to extend the functionality &amp;amp; customise the behaviour.
It is extremely extensible.&lt;/p&gt;
&lt;h4&gt;Inference Server&lt;/h4&gt;
&lt;p&gt;Ollama MLX doesn't generate tokens efficiently.&lt;/p&gt;
&lt;p&gt;Rapix-MLX, omlx are excellent at utilizing resources and generating tokens efficiently.
With M5 Pro 48GB RAM, they are able to generate ~50 tokens/second with &lt;code&gt;Qwen3.6-35B-A3B-4bit&lt;/code&gt; model.&lt;/p&gt;
&lt;p&gt;Llama.cpp is cross-platform and it is extremely fast as well.&lt;/p&gt;
&lt;h4&gt;Local LLMs&lt;/h4&gt;
&lt;p&gt;&lt;img alt="dense vs moe" src="https://avilpage.com/images/dense-vs-moe-llm.svg"&gt;&lt;/p&gt;
&lt;p&gt;Qwen3.6-35B-A3B model made locall LLMs usable on decent hardware. &lt;/p&gt;
&lt;p&gt;Qwen3.6-35B-A3B - has 35B parameters &amp;amp; only 3B are active at a time. I use 4bit quantized model as it provides
a better tradeoff between speed and accuracy. It fits in 48GB RAM with some headroom for other applications.&lt;/p&gt;
&lt;p&gt;Bonsai has highest intelligent densisty and it can run on ~5 GB RAM.&lt;/p&gt;
&lt;p&gt;It is surprising how fast &amp;amp; powerful the local LLMs have become.&lt;/p&gt;</description><category>AI</category><category>macbook</category><guid>https://avilpage.com/2026/08/how-i-run-llms-locally-on-mac.html</guid><pubDate>Thu, 27 Aug 2026 17:03:44 GMT</pubDate></item><item><title>Handy - Best cross platform Dictation app (Free)</title><link>https://avilpage.com/2026/07/handy-stt-dictation-cross-platform.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Context&lt;/h4&gt;
&lt;p&gt;Around 2016, I explored various speech-to-text (STT) tools to reduce strain on writs due to RSI(Repetetive Strain Injury) and gave up on them due to their limitations.&lt;/p&gt;
&lt;p&gt;With AI advancements, these tools have come a long way.&lt;/p&gt;
&lt;h4&gt;Open Source STT Tools&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/cjpais/Handy"&gt;Handy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/TypeWhisper"&gt;TypeWhisper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/altic-dev/FluidVoice"&gt;FluidVoice&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ray-amjad/hyperwhisper-app"&gt;HyperWhisper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Beingpax/VoiceInk"&gt;VoiceInk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are couple of paid tools but they didn't work well in noisy environment.&lt;/p&gt;
&lt;p&gt;After trying out all these tools with local models like Parakeet, Voxstral, and Cohere Transcribe, I found that Handy + Cohere Transcribe is the best combination for my needs.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mac-tts-models.png" src="https://avilpage.com/images/mac-tts-models.png"&gt;&lt;/p&gt;
&lt;p&gt;Handy has post processing as an experimental feature where we can send output of STT to other LLM models and get a fine grained output.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mac-tts-post-process.png" src="https://avilpage.com/images/mac-tts-post-process.png"&gt;&lt;/p&gt;
&lt;p&gt;For example, when I dictate "git push dash dash force", the output is "git push --force" after post processing.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;I let AI to write &lt;a href="https://github.com/ChillarAnand/init/blob/main/handy_stats.py"&gt;handy_stats.py&lt;/a&gt; script to track my dictation stats. I am dictating more than 10K characters per day which reduces strain on my fingers/writs.&lt;/p&gt;</description><category>cross-platform</category><category>dictation</category><category>speech-to-text</category><guid>https://avilpage.com/2026/07/handy-stt-dictation-cross-platform.html</guid><pubDate>Tue, 28 Jul 2026 23:49:39 GMT</pubDate></item><item><title>Moving from TailScale to NetBird</title><link>https://avilpage.com/2026/06/moving-from-tailscale-to-netbird.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Why?&lt;/h4&gt;
&lt;p&gt;I have been using &lt;a href="https://avilpage.com/tags/tailscale.html"&gt;TailScale&lt;/a&gt; from 4 years. 
Recently, I wanted to self-host HeadScale(open source TailScale server) on my own server. &lt;/p&gt;
&lt;p&gt;During self hosting, I realised that HeadScale is not a drop-in replacement for TailScale.&lt;/p&gt;
&lt;p&gt;App connectors are main reason I was using TailScale and HeadScale &lt;a href="https://github.com/juanfont/headscale/issues/1651"&gt;doesn't support app-connectors&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;NetBird&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/netbirdio/netbird"&gt;NetBird&lt;/a&gt; is completely open source and has a self-hosted server. 
Setting up split DNS tunneling and routing is easier with NetBird.&lt;/p&gt;
&lt;p&gt;It has a clean web UI to manage network/policies which is way better than TailScale's web UI.&lt;/p&gt;
&lt;p&gt;It also has a cool control center to visualize the network and connected devices.&lt;/p&gt;
&lt;p&gt;&lt;img alt="netbird" src="https://avilpage.com/images/netbird.png"&gt;&lt;/p&gt;
&lt;p&gt;It still doesn't have support for light theme yet. 
Since I am not accustomed to dark theme, I am using &lt;a href="https://github.com/openstyles/stylus"&gt;Stylus&lt;/a&gt; extension
and changing the theme to light theme.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;invert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hue-rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="kt"&gt;deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;video&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s2"&gt;"background-image"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;invert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hue-rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="kt"&gt;deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;NetBird can be self-hosted in few minutes and migration is much smoother than I expected. &lt;/p&gt;</description><category>networking</category><category>self-hosting</category><guid>https://avilpage.com/2026/06/moving-from-tailscale-to-netbird.html</guid><pubDate>Sat, 27 Jun 2026 05:43:54 GMT</pubDate></item><item><title>Everyday AI Tools</title><link>https://avilpage.com/2026/05/everyday-ai-tools.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;CLI Tools: GitHub Copilot CLI, Claude Code &amp;amp; Open Code&lt;/p&gt;
&lt;p&gt;IDE: GitHub Copilot Plugin&lt;/p&gt;
&lt;h4&gt;Caveman&lt;/h4&gt;
&lt;p&gt;&lt;img alt="caveman" src="https://avilpage.com/images/caveman.png"&gt;&lt;/p&gt;
&lt;p&gt;Reduces token usage by eliminating clutter. It doesn't affect thinking/reasoning.&lt;/p&gt;
&lt;p&gt;Alternatives: &lt;a href="https://avilpage.com/2026/05/everyday-ai-tools.html"&gt;Ponytail&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These tools will help in saving more than 30% of our time to read model output and money(tokens).&lt;/p&gt;
&lt;h4&gt;Claude-mem&lt;/h4&gt;
&lt;p&gt;&lt;img alt="claude-mem" src="https://avilpage.com/images/claude-mem.png"&gt;&lt;/p&gt;
&lt;p&gt;Claude-mem preserves context across sessions by automatically capturing tool usage observations, 
generating semantic summaries, and making them available to future sessions. 
This enables Claude to maintain continuity of knowledge about projects even after sessions end or reconnect.&lt;/p&gt;
&lt;p&gt;This will improve developer productivity as well.&lt;/p&gt;
&lt;p&gt;Alternatives: &lt;a href="https://github.com/rohitg00/agentmemory"&gt;AgentMemory&lt;/a&gt; (backed by Linux Foundation)&lt;/p&gt;
&lt;h4&gt;CodeGraph&lt;/h4&gt;
&lt;p&gt;We work with multiple code bases on a daily basis and claude-code spawns Explore agents 
that scan files with grep, glob and read. They consume tokens on every tool call.&lt;/p&gt;
&lt;p&gt;CodeGraph provides a pre-indexed knowledge graph to those agents, which reduces 50% tokens.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Alternatives&lt;/em&gt;: &lt;a href="https://github.com/safishamsi/graphify"&gt;Graphify&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;rtk&lt;/h4&gt;
&lt;p&gt;CLI proxy that reduces LLM token consumption by ~75% on common dev commands like ls, cat, git, etc.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Similar tool&lt;/em&gt;: &lt;a href="https://github.com/headroomlabs-ai/headroom"&gt;Headroom&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Misc&lt;/h4&gt;
&lt;p&gt;andrej-karpathy-skills&lt;/p&gt;
&lt;p&gt;ccstatusline&lt;/p&gt;
&lt;p&gt;Custom instructions for agents in plain markdown files&lt;/p&gt;</description><category>AI</category><guid>https://avilpage.com/2026/05/everyday-ai-tools.html</guid><pubDate>Sun, 31 May 2026 17:47:04 GMT</pubDate></item><item><title>First 30 Days in a Senior Technical Role</title><link>https://avilpage.com/2026/04/first-30-days-senior-tech-role.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;A little trust goes a long way&lt;/h4&gt;
&lt;p&gt;As a senior technical person, you will have certain professional authority.
But to be effective, you need to build personal trust with your team and peers.
That can happen only if you are approachable &amp;amp; transparent.&lt;/p&gt;
&lt;p&gt;Set up 1:1 meetings with your team members and cross-functional team leads.
Go on a listening tour and take your notes.&lt;/p&gt;
&lt;p&gt;Be specific on how people can reach you and how you will communicate with them.
Setup routine 1:1 meetings if required.&lt;/p&gt;
&lt;h4&gt;Follow the money&lt;/h4&gt;
&lt;p&gt;It is important to have high level overview of the business. 
This will help you make informed decisions and prioritize your work effectively.&lt;/p&gt;
&lt;p&gt;&lt;img alt="follow the money" src="https://avilpage.com/images/follow-the-money.png"&gt;&lt;/p&gt;
&lt;center&gt;
&lt;i&gt;
Sankey chart of Apple's revenue
&lt;/i&gt;
&lt;/center&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;If the company is public, you can get quarterly &amp;amp; annual reports.
If not, try to get a good sense of where the money is coming from and where the money is going.&lt;/p&gt;
&lt;h4&gt;Follow the data&lt;/h4&gt;
&lt;p&gt;Get a high level overview of product(s), infrastructure, tools, data flow.
This is crucial to make informed technical decisions or architectural changes.&lt;/p&gt;
&lt;h4&gt;Start Small&lt;/h4&gt;
&lt;p&gt;For the first 30 days, you should be in "listening mode" or "absorbing mode".
Try to understand the company, the team, the product, the customers, the culture, and the processes.&lt;/p&gt;
&lt;p&gt;It is better to avoid any big changes in the first 30 days. There will be plenty of time for that later.&lt;/p&gt;
&lt;h4&gt;30-60-90 Day Plan&lt;/h4&gt;
&lt;p&gt;Note down action items for next 60 and 90 days.&lt;/p&gt;
&lt;p&gt;It could be anything from setting up a new monitoring system,
to improving the deployment process, to hiring new team members, providing simple tools for self service, etc.&lt;/p&gt;
&lt;p&gt;Commnicate the plan with all stakeholders and avoid any surprises.&lt;/p&gt;
&lt;h4&gt;Reduce Cloud &amp;amp; SaaS Costs&lt;/h4&gt;
&lt;p&gt;If these are a significant part of the company's expenses,
then review the costs and see if there is any room for reducing these costs.&lt;/p&gt;
&lt;p&gt;On cloud, moving compute instances to reserved or spot can save 70-90% of costs.&lt;/p&gt;
&lt;p&gt;That can have a big impact on the company's bottom line.&lt;/p&gt;
&lt;h4&gt;Buy or build good tools&lt;/h4&gt;
&lt;p&gt;On the other hand, if there are any tools that can help the team to be more productive, 
then it is worth investing in those tools.&lt;/p&gt;
&lt;p&gt;To do that, you should already have a good toolset under your belt.&lt;/p&gt;
&lt;p&gt;Sometimes building a simple tool which can make team self sufficient 
can have a big impact on the team's productivity and morale.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;The first 30 days in a senior technical role are crucial for building trust, 
understanding the business, and setting the foundation for the next step.&lt;/p&gt;
&lt;p&gt;Without much work to do, you can have a big impact on the company by following the tips mentioned above.&lt;/p&gt;</description><category>careers</category><guid>https://avilpage.com/2026/04/first-30-days-senior-tech-role.html</guid><pubDate>Thu, 30 Apr 2026 06:17:29 GMT</pubDate></item><item><title>Build/Deploy Full Stack Web Apps with only Config</title><link>https://avilpage.com/2026/03/config-first-tools.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;blockquote&gt;
&lt;p&gt;The best code is the code you don't have to write&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Config First Tools&lt;/h4&gt;
&lt;p&gt;Any tool that provides first class support for configuration files can be considered a Config First Tool. 
These tools allow developers to setup/build/deploy applications by writing configuration files instead of writing code.&lt;/p&gt;
&lt;p&gt;In DevOps world, tools like Terraform, Ansible, and Kubernetes are examples of Config First Tools. 
These kinds of tools are not that popular in the web development world.&lt;/p&gt;
&lt;p&gt;In this article, lets see how we can build a full stack web application using only configuration files.&lt;/p&gt;
&lt;h4&gt;Todo - Web App&lt;/h4&gt;
&lt;p&gt;A simple backend API that allows users to manage todo lists.
A simple frontend that uses the backend API.
A simple script to deploy the backend and frontend applications.&lt;/p&gt;
&lt;h4&gt;Backend API&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://pocketbase.io/"&gt;PocketBase&lt;/a&gt; is a backend API that provides a simple way to create and manage databases, authentication, and file storage.
It is a great tool for building simple backend APIs without writing any code.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;pocketbase
$&lt;span class="w"&gt; &lt;/span&gt;pocketbase&lt;span class="w"&gt; &lt;/span&gt;serve
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create a collection called &lt;code&gt;Todo&lt;/code&gt; with required fields and pocketbase will automatically generate the API for us.&lt;/p&gt;
&lt;p&gt;&lt;img alt="config-first-tools" src="https://avilpage.com/images/config-first-tools-backend.png"&gt;&lt;/p&gt;
&lt;h4&gt;Frontend&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://lowdefy.com/"&gt;Lowdefy&lt;/a&gt; is a config first tool that allows us to build web applications using yaml config.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;npm&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;lowdefy
$&lt;span class="w"&gt; &lt;/span&gt;lowdefy&lt;span class="w"&gt; &lt;/span&gt;init
$&lt;span class="w"&gt; &lt;/span&gt;lowdefy&lt;span class="w"&gt; &lt;/span&gt;dev
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For basic crud apps, instead of us writing the boilerplate config, we can ask an AI agent to write the config for us.&lt;/p&gt;
&lt;h4&gt;Deployment&lt;/h4&gt;
&lt;p&gt;For deployment, we can use Ansible to deploy both the backend and frontend applications. Here also we can just AI agent to write the playbook for us.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;ansible
$&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook&lt;span class="w"&gt; &lt;/span&gt;deploy.yml
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;OliveTin&lt;/h4&gt;
&lt;p&gt;&lt;img alt="config-first-tools" src="https://avilpage.com/images/config-first-tools-devops.png"&gt;&lt;/p&gt;
&lt;p&gt;Even though we can use ansible to deploy the applications, it is not that convenient to run ansible playbooks on mobile.
&lt;a href="https://www.olivetin.app"&gt;OliveTin&lt;/a&gt; is a config first tool that allows us to create web UIs for our scripts.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Deploy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ToDo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;App"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;popupOnStart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;execution-dialog&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible-playbook deploy.yml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;6000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"🤖"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create a simple web UI for our deployment script with just 5 lines.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;For quick prototyping and simple applications, config first tools can be a great choice as they allow us to build applications without writing any code.
They also allow us to focus on the application logic rather than the implementation details.&lt;/p&gt;
&lt;p&gt;With the rise of AI, it is much easy to maintain 500 lines of config than 5000 lines of code.&lt;/p&gt;</description><category>AI</category><category>devops</category><category>web development</category><guid>https://avilpage.com/2026/03/config-first-tools.html</guid><pubDate>Sat, 28 Mar 2026 06:17:29 GMT</pubDate></item><item><title>Talk: Classify Billion base pairs per Second</title><link>https://avilpage.com/2026/02/classify-billion-base-pairs-per-second.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;During 25th Feb 2026, a &lt;a href="https://www.meetup.com/bangpypers/events/311155506"&gt;joint meetup&lt;/a&gt; was hosted by BangPypers &amp;amp; SciPy India. &lt;/p&gt;
&lt;p&gt;There was a slot for lightning talk &amp;amp; I gave a talk on Kraken2 performance optimisations titled as "Classify billion base pairs per second".&lt;/p&gt;
&lt;p&gt;Since it was a lightning talk, I didn't had time to polish the slides. During the talk, I briefly covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is metagenomics?&lt;/li&gt;
&lt;li&gt;Overview of open source classification tools &lt;/li&gt;
&lt;li&gt;Brief intro to Kraken2&lt;/li&gt;
&lt;li&gt;Performance optimizations in Kraken2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Few years back, I wrote a series of posts on &lt;a href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html"&gt;Mastering Kraken2&lt;/a&gt; where I covered all the optimizations in detail.
If you want to dig deeper into the topic, you can check out the series.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/anand-talk-kraken.png" alt="Anand's talk on Kraken" width="600"&gt;&lt;/p&gt;</description><category>talks</category><guid>https://avilpage.com/2026/02/classify-billion-base-pairs-per-second.html</guid><pubDate>Sat, 28 Feb 2026 01:27:43 GMT</pubDate></item><item><title>In Praise of OliveTin</title><link>https://avilpage.com/2026/01/in-praise-of-olivetin.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img alt="olivetin" src="https://avilpage.com/images/olivetin.png"&gt;&lt;/p&gt;
&lt;p&gt;In a world of complex internal tools, &lt;a href="https://www.olivetin.app"&gt;OliveTin&lt;/a&gt; bridges the gap between raw CLI and usable web UI with just yaml config.&lt;/p&gt;
&lt;h4&gt;Server Admin Panel&lt;/h4&gt;
&lt;p&gt;I used admin panels like &lt;a href="https://avilpage.com/2024/12/install-cockpit-on-remote-linux-vm.html"&gt;CockPit&lt;/a&gt;, Ajenti, etc to provide simple web UI 
for non-developers to provide access to services. Developing custom widgets is time consuming and requires programming skills as well.&lt;/p&gt;
&lt;p&gt;With OliveTin, I can provide web UI directly with just yaml config. This saves a lot of time and effort.
It also provides a clean UI as it starts from scratch.&lt;/p&gt;
&lt;h4&gt;Backend Driven UI&lt;/h4&gt;
&lt;p&gt;For existing python scripts, I often use tools like Streamlit, NiceGUI, etc to create web UIs.
Organizing the UI components for multiple scripts is time consuming.&lt;/p&gt;
&lt;p&gt;OliveTin can provide web UI directly python scripts and they can be organized in groups with just yaml config.&lt;/p&gt;
&lt;h4&gt;Mobile Friendly&lt;/h4&gt;
&lt;p&gt;To do a simple deployment on mobile, I need to open an app that supports ssh, ssh into the server, navigate to a directory, 
run a script to deploy.&lt;/p&gt;
&lt;p&gt;OliveTin provides a "Deploy" button on mobile browser which is way convenient.&lt;/p&gt;
&lt;h4&gt;Authentication&lt;/h4&gt;
&lt;p&gt;&lt;img alt="olivetin-oauth2" src="https://avilpage.com/images/olivetin-oauth2.png"&gt;&lt;/p&gt;
&lt;p&gt;OliveTin provides authentication(local users, OAuth2, JWT, etc), authorization(ACLs) &amp;amp; accounting(logs) out of the box.
With just yaml config, we can secure the web UI.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;There are hundreds of other features provided by OliveTin like scheduling, file uploads, webhooks, etc.&lt;/p&gt;
&lt;p&gt;If you ever want to provide a simple web UI for scripts with low code or no code, give OliveTin a try!&lt;/p&gt;</description><category>automation</category><category>cross-platform</category><category>devops</category><guid>https://avilpage.com/2026/01/in-praise-of-olivetin.html</guid><pubDate>Fri, 30 Jan 2026 20:13:11 GMT</pubDate></item><item><title>Remote Access to k3d/k3s Kubernetes cluster</title><link>https://avilpage.com/2025/12/remote-access-to-k3d-k3s-cluster.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;We learnt how to &lt;a href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html"&gt;deploy kubernetes cluster anywhere with a single k3d command&lt;/a&gt;. 
By default, k3d cluster is accessible only from the host machine.&lt;/p&gt;
&lt;h4&gt;Remote Access&lt;/h4&gt;
&lt;p&gt;&lt;img alt="k3d-remote-access" src="https://avilpage.com/images/k3s-remote-access.png"&gt;&lt;/p&gt;
&lt;p&gt;Create new cluster with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;k3d&lt;span class="w"&gt; &lt;/span&gt;cluster&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;cloud-k8s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--api-port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6443&lt;/span&gt;:6443@loadbalancer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--k3s-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--tls-san=&amp;lt;remote-ip&amp;gt;@server:*"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--api-port 6443:6443@loadbalancer&lt;/code&gt; maps port 6443 on the host machine to the cluster's API server load balancer. 
This can be changed (e.g., 8080:6443) if 6443 is taken on the host.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--k3s-arg "--tls-san=..."&lt;/code&gt;  adds the host's public IP to the certificate, preventing SSL errors later.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ensure remote server firewall allows incoming traffic on the chosen port (e.g., 6443 or 8080). 
To verify, run &lt;code&gt;telnet &amp;lt;remote-ip&amp;gt; 6443&lt;/code&gt; from local machine.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the remote server, get kubeconfig:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;k3d&lt;span class="w"&gt; &lt;/span&gt;kubeconfig&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;cloud-k8s
---
apiVersion:&lt;span class="w"&gt; &lt;/span&gt;v1
clusters:
-&lt;span class="w"&gt; &lt;/span&gt;cluster:
&lt;span class="w"&gt;    &lt;/span&gt;server:&lt;span class="w"&gt; &lt;/span&gt;https://0.0.0.0:6443
&lt;span class="w"&gt;  &lt;/span&gt;name:&lt;span class="w"&gt; &lt;/span&gt;k3d-rk
&lt;span class="w"&gt;   &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# truncated for brevity&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Copy this kubeconfig, replace &lt;code&gt;0.0.0.0&lt;/code&gt; with the remote server's public IP.&lt;/p&gt;
&lt;p&gt;Open &lt;a href="https://github.com/freelensapp/freelens"&gt;Free Lens&lt;/a&gt;, paste this config and connect to the remote k3d cluster.&lt;/p&gt;
&lt;p&gt;&lt;img alt="k3d-remote-access" src="https://avilpage.com/images/k3s-remote-access-freelens.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;You can use your favorite Kubernetes tools (kubectl, FreeLens, k9s, etc.) to manage the remote k8s cluster.&lt;/p&gt;</description><category>devops</category><category>kubernetes</category><category>linux</category><guid>https://avilpage.com/2025/12/remote-access-to-k3d-k3s-cluster.html</guid><pubDate>Wed, 17 Dec 2025 03:10:39 GMT</pubDate></item><item><title>Setup Tailscale App Connector in 3 easy steps</title><link>https://avilpage.com/2025/11/tailscale-app-connectors-quick-setup.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem Statement&lt;/h4&gt;
&lt;p&gt;In the earlier post, we have seen how to &lt;a href="https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html"&gt;route specific websites to an exit node&lt;/a&gt; using a SOCKS proxy &amp;amp; browser extension(or a PAC file).&lt;/p&gt;
&lt;p&gt;With this approach, when we need to work on multiple computers, we need to setup the SOCKS proxy &amp;amp; browser extension individually.&lt;/p&gt;
&lt;p&gt;Instead we can use Tailscale's App Connectors to route specific websites through selected nodes.&lt;/p&gt;
&lt;p&gt;Tailscale docs are too complicated for this App connectors. Here is a simplified version of the steps.&lt;/p&gt;
&lt;h4&gt;Tailscale - App Connectors&lt;/h4&gt;
&lt;p&gt;Note: There is no need for publicly reachable IP address for the Tailscale node which is used as App Connector.
(Thanks &lt;a href="https://chameth.com"&gt;Chris Smith&lt;/a&gt; for pointing it out. Tailscale docs are misleading in this regard.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the Tailscale admin console, go to the "Access control" section &amp;amp; add &lt;code&gt;tagOwners&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"tagOwners"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"tag:home-connector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;"autogroup:member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="tailscale app connector acl" src="https://avilpage.com/images/tailscale-app-connector-acl.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use any Linux machine (it doesn't need static IP) to setup the App Connector. Install Tailscale on it. Advertise it as an app connector.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tailscale&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;--advertise-tags&lt;span class="o"&gt;=&lt;/span&gt;tag:home-connector&lt;span class="w"&gt; &lt;/span&gt;--accept-routes
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Enable IP forwarding on the machine. If your Linux system has a &lt;code&gt;/etc/sysctl.d&lt;/code&gt; directory, run&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'net.ipv4.ip_forward = 1'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;/etc/sysctl.d/99-tailscale.conf
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'net.ipv6.conf.all.forwarding = 1'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;/etc/sysctl.d/99-tailscale.conf
sudo&lt;span class="w"&gt; &lt;/span&gt;sysctl&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/etc/sysctl.d/99-tailscale.conf
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Otherwise, run&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;From the Tailscale admin console, create a new app connector.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="tailscale app connector" src="https://avilpage.com/images/tailscale-app-connector.png"&gt;&lt;/p&gt;
&lt;p&gt;In the "Target" field, we can select any existing app or we can use custom target so that we can route our desired websites.
For now, I am adding &lt;code&gt;ip.me&lt;/code&gt; domain so that we can verify if the traffic is routed through the connector.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From the "Machines" page, select the device and approve the requested subnets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="tailscale app connector subnet" src="https://avilpage.com/images/tailscale-app-connector-subnet.png"&gt;&lt;/p&gt;
&lt;p&gt;From browser, lets visit 2ip.io to see our device ip address. Next, lets visit ip.me to ensure we are seeing the connector's IP as this domain will be served by app connector.&lt;/p&gt;
&lt;p&gt;&lt;img alt="tailscale app connector verify" src="https://avilpage.com/images/tailscale-app-connector-verify.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We can use App Connectors to route specific websites through a Tailscale node without needing to setup SOCKS proxy or browser extensions on each device.&lt;/p&gt;</description><category>networking</category><category>tailscale</category><guid>https://avilpage.com/2025/11/tailscale-app-connectors-quick-setup.html</guid><pubDate>Sat, 22 Nov 2025 12:48:18 GMT</pubDate></item><item><title>TailScale - Use Exit Node for Specific Websites only</title><link>https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/tags/tailscale.html"&gt;Tailscale&lt;/a&gt;&lt;sup id="fnref:tailscale"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html#fn:tailscale"&gt;1&lt;/a&gt;&lt;/sup&gt; provides zero-config mesh VPN built on top of Wiregaurd.&lt;/p&gt;
&lt;p&gt;It provides an option to use an exit node for routing all traffic through it. 
But it can't route only specific domains through the exit node.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Tailscale Exit Node Option" src="https://avilpage.com/images/tailscale-exit-node-option.png"&gt;&lt;/p&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;p&gt;Setup a SOCKS proxy using &lt;code&gt;ssh&lt;/code&gt; command line tool.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;-N&lt;span class="w"&gt; &lt;/span&gt;user@exit-node-ip
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;-D 1080&lt;/code&gt; : Specifies the local port to listen on for SOCKS connections.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-f&lt;/code&gt; : Requests ssh to go to background just before command execution.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-C&lt;/code&gt; : Enables compression.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-q&lt;/code&gt; : Quiet mode.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-N&lt;/code&gt; : Do not execute remote commands.&lt;/p&gt;
&lt;p&gt;Once it is started, we can use &lt;a href="https://github.com/zero-peak/ZeroOmega"&gt;ZeroOmega&lt;/a&gt;&lt;sup id="fnref:zeroomega"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html#fn:zeroomega"&gt;2&lt;/a&gt;&lt;/sup&gt; browser extension to route specific domains through the SOCKS proxy.&lt;/p&gt;
&lt;p&gt;&lt;img alt="ZeroOmega Config" src="https://avilpage.com/images/zeroomega-config.png"&gt;&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;auto switch&lt;/code&gt; profile, we can setup specific domains which needs to be directed to the proxy. 
For all other domains, it will use the direct connection.&lt;/p&gt;
&lt;p&gt;This works only for the browser where the extension is installed.&lt;/p&gt;
&lt;p&gt;To apply this at the system level, we can use &lt;code&gt;pac&lt;/code&gt; file and update the system proxy settings to use the &lt;code&gt;pac&lt;/code&gt; file.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Tailscale provides app connector feature to route specific apps through the exit node, but it is needs publicly reachable IPs &amp;amp; Linux based OS for now.&lt;/p&gt;
&lt;p&gt;Setting up SOCKS proxy &amp;amp; using a browser extension or PAC file is much easy &amp;amp; straight forward solution to route specific domains through Tailscale exit node.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:tailscale"&gt;
&lt;p&gt;&lt;a href="https://tailscale.com"&gt;https://tailscale.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html#fnref:tailscale" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:zeroomega"&gt;
&lt;p&gt;&lt;a href="https://github.com/zero-peak/ZeroOmega"&gt;https://github.com/zero-peak/ZeroOmega&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html#fnref:zeroomega" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>how-to</category><category>tailscale</category><guid>https://avilpage.com/2025/10/tailscale-exit-node-specific-domains.html</guid><pubDate>Wed, 22 Oct 2025 22:20:58 GMT</pubDate></item><item><title>MacBook - Natural Scrolling for Mouse</title><link>https://avilpage.com/2025/09/macbook-natural-scrolling-mouse.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem&lt;/h4&gt;
&lt;p&gt;If we connect a mouse to macOS, the scrolling direction changes to "unnatural" for the mouse. 
This is because macOS has a single setting for natural scrolling that applies to both trackpad and mouse.&lt;/p&gt;
&lt;p&gt;&lt;img alt="macos mouse settings" src="https://avilpage.com/images/macos-mouse-natural-scrolling00.png"&gt;&lt;/p&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;p&gt;To have natural scrolling for both trackpad and mouse, we can use third-party tools like 
&lt;a href="https://github.com/ther0n/UnnaturalScrollWheels"&gt;UnnaturalScrollWheels&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If we already use &lt;a href="https://karabiner-elements.pqrs.org/"&gt;Karabiner-Elements&lt;/a&gt;, we can use it to set natural scrolling for mouse separately.&lt;/p&gt;
&lt;p&gt;Open Karabiner-Elements and go to the "Devices" tab, select your mouse, and click on "Open mouse settings".&lt;/p&gt;
&lt;p&gt;&lt;img alt="Karabiner-Elements Devices Tab" src="https://avilpage.com/images/macos-mouse-natural-scrolling11.png"&gt;&lt;/p&gt;
&lt;p&gt;In the mouse settings, check the "Flip mouse vertical wheel" option.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Karabiner-Elements Devices Tab" src="https://avilpage.com/images/macos-mouse-natural-scrolling22.png"&gt;&lt;/p&gt;
&lt;p&gt;Now, both trackpad and mouse will have natural scrolling.&lt;/p&gt;</description><category>how-to</category><category>macbook</category><guid>https://avilpage.com/2025/09/macbook-natural-scrolling-mouse.html</guid><pubDate>Tue, 30 Sep 2025 18:20:58 GMT</pubDate></item><item><title>Mutual Funds - Behind the scenes</title><link>https://avilpage.com/2025/08/mutual-funds-behind-the-scenes.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;As investors, we buy mutual funds from fund houses, platforms, or from distributors. 
But have you ever wondered what happens behind the scenes? How do these funds operate, and what processes are involved in managing them? 
In this post, we'll explore the behind-the-scenes operations of mutual funds.&lt;/p&gt;
&lt;h4&gt;Structure of a Mutual Fund&lt;/h4&gt;
&lt;p&gt;&lt;img alt="Mutual Fund Structure" src="https://avilpage.com/images/mutual-fund-structure.png"&gt;&lt;/p&gt;
&lt;p&gt;In India, mutual funds have 3-tier structure consisting of the Sponsor, the Trust &amp;amp; the Asset Management Company (AMC). &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The sponsor establishes the mutual fund and is responsible for its operations. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The trust &amp;amp; trustees are responsible for safeguarding investor interests, supervising the AMC's operations,
and ensuring compliance with regulations.
Custodians are appointed to hold the securities of the mutual fund and ensure their safekeeping.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AMC is the core entity responsible for the day-to-day management of the mutual fund. &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The legal seperation of Trust &amp;amp; AMC ensures that the interests of investors are protected, and the fund's assets are managed independently.&lt;/p&gt;
&lt;p&gt;All AMCs are registered with the Securities and Exchange Board of India (SEBI) and the list is available on the &lt;a href="https://avilpage.com/2025/08/mutual-funds-behind-the-scenes.html"&gt;SEBI website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can look at SBI MF details from AMFI to understand the structure better.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Mutual Fund Structure" src="https://avilpage.com/images/mutual-fund-structure2.png"&gt;&lt;/p&gt;
&lt;h4&gt;Mutual Fund Transactions&lt;/h4&gt;
&lt;p&gt;&lt;img alt="Mutual Fund Transactions" src="https://avilpage.com/images/mutual-fund-transaction.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RIA&lt;/strong&gt;: 
Investors can use RIA (Registered Investment Advisor) platforms like &lt;a href="https://groww.in/"&gt;Groww&lt;/a&gt;, &lt;a href="https://coin.zerodha.com/"&gt;Zerodha Coin&lt;/a&gt;, to invest in direct mutual funds.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MFD&lt;/strong&gt;
Alternatively, they can also buy regular mutual funds through distributors like NJWealth, PhonePhe etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TEP&lt;/strong&gt;:
To process these transactions, Trading &amp;amp; Execution Platforms like BSE Star MF, NSE MFSS, etc are available. 
These platforms facilitate the buying and selling of mutual fund units, ensuring that transactions are executed efficiently and accurately.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RTA&lt;/strong&gt;:
RTA(Registrar and Transfer Agent) plays a crucial role in maintaining investor records, processing transactions, and ensuring compliance with regulatory requirements.&lt;/p&gt;
&lt;p&gt;Investors can also buy mutual funds directly from the fund house's website or through their mobile app.&lt;/p&gt;
&lt;p&gt;These mutual funds can be stored in Demat account or in physical form as account statements.
It depends on the platform or fund house you choose to invest with.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;This post provided a brief overview of the behind-the-scenes operations of mutual funds in India.&lt;/p&gt;</description><category>finance</category><category>investing</category><guid>https://avilpage.com/2025/08/mutual-funds-behind-the-scenes.html</guid><pubDate>Tue, 19 Aug 2025 02:32:52 GMT</pubDate></item><item><title>Setup Raspberry Pi without Monitor &amp; Keyboard</title><link>https://avilpage.com/2025/07/setup-raspberry-pi-without-monitor-keyboard.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Requirements&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Raspberry Pi (any model)&lt;/li&gt;
&lt;li&gt;MicroSD card (8GB or larger)&lt;/li&gt;
&lt;li&gt;Power supply&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Setup&lt;/h4&gt;
&lt;p&gt;Download &amp;amp; install Raspberry Pi Imager from &lt;a href="https://www.raspberrypi.com/software/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="![Raspberry Pi Imager]" src="https://avilpage.com/images/rpi-setup0.png"&gt;&lt;/p&gt;
&lt;p&gt;After installation, connect SD Card to Computer, and start installation process.&lt;/p&gt;
&lt;p&gt;In the config step, setup WiFi credentials and enable ssh server as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt="![Raspberry Pi Imager]" src="https://avilpage.com/images/rpi-setup.png"&gt;&lt;/p&gt;
&lt;p&gt;Once the installation is complete, insert the SD card into the Raspberry Pi and power it on.&lt;/p&gt;
&lt;h4&gt;Find the IP Address&lt;/h4&gt;
&lt;p&gt;You can find the IP address of your Raspberry Pi by checking your router's connected devices list or using a network scanning tool like &lt;code&gt;nmap&lt;/code&gt; or &lt;code&gt;arp&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;arp&lt;span class="w"&gt; &lt;/span&gt;-an

&lt;span class="c1"&gt;# or using nmap&lt;/span&gt;
nmap&lt;span class="w"&gt; &lt;/span&gt;-sn
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once you have the IP address, you can SSH into the Raspberry Pi.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;pi@&amp;lt;IP_ADDRESS&amp;gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;When we don't have a monitor and/or keyboard, this process allows us to set up a Raspberry Pi headlessly. This is particularly useful for projects where the Pi will be used as a server or in a remote location.&lt;/p&gt;</description><category>headless</category><category>raspberry_pi</category><guid>https://avilpage.com/2025/07/setup-raspberry-pi-without-monitor-keyboard.html</guid><pubDate>Thu, 31 Jul 2025 03:50:56 GMT</pubDate></item><item><title>Raycast replaced 10 macOS apps</title><link>https://avilpage.com/2025/06/raycast-replaced-10-macos-apps.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Since I started using Raycast, I have replaced many macOS apps with it. 
Here is a list of those apps and their Raycast equivalents.&lt;/p&gt;
&lt;h4&gt;Espanso&lt;/h4&gt;
&lt;p&gt;Instead of using Espanso for text expansion, I now use Raycast's built-in text snippets feature.&lt;/p&gt;
&lt;h4&gt;Hotkey&lt;/h4&gt;
&lt;p&gt;I used to use Hotkey to assign keyboard shortcuts to various actions. Now, I use Raycast's built-in hotkeys feature to achieve the same functionality.&lt;/p&gt;
&lt;h4&gt;Fly Cut&lt;/h4&gt;
&lt;p&gt;I used to use Fly Cut for clipboard management, but now I rely on Raycast's clipboard history feature to access my clipboard items quickly.&lt;/p&gt;
&lt;h4&gt;FinderGO&lt;/h4&gt;
&lt;p&gt;I used to use FinderGO to quickly navigate to specific folders in Finder. Now, I use Raycast's built-in file navigation feature to achieve the same functionality.&lt;/p&gt;
&lt;h4&gt;Rectangle&lt;/h4&gt;
&lt;p&gt;To move and resize windows, I used to use Rectangle. Now, I use Raycast's built-in window management feature to achieve the same functionality.&lt;/p&gt;
&lt;h4&gt;Textbar&lt;/h4&gt;
&lt;p&gt;Instead of using Textbar to copy TOTP for two-factor authentication, I now use Raycast's extension "One Time Password" to generate and copy TOTP codes directly.&lt;/p&gt;
&lt;h4&gt;Caffenate&lt;/h4&gt;
&lt;p&gt;To prevent my Mac from sleeping, instead of using Caffenate, I now use Raycast's built-in "Caffeinate" command to keep my Mac awake.&lt;/p&gt;
&lt;h4&gt;Calculator&lt;/h4&gt;
&lt;p&gt;Instead of using Python prompt for basic arithmetic calculations, I now use Raycast's built-in calculator feature to perform quick calculations.
This is super convenient and saves me from opening a separate calculator app.&lt;/p&gt;
&lt;h4&gt;Hammer Spoon (partially)&lt;/h4&gt;
&lt;p&gt;To assign shortcuts to browser urls, shell scripts, and other actions, I used to use Hammer Spoon. 
Now, I use Raycast's built-in scripting capabilities to create custom commands and assign shortcuts to them.&lt;/p&gt;
&lt;h4&gt;Terminal (partially)&lt;/h4&gt;
&lt;p&gt;For things like killing processes, installing packages, and running shell commands, I used to rely on Terminal.
Now, I use Raycast's built-in terminal integration to run shell commands directly from the Raycast interface.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;With Raycast, I have been able to streamline my workflow by replacing multiple macOS apps with its powerful features.&lt;/p&gt;</description><category>macbook</category><category>productivity</category><guid>https://avilpage.com/2025/06/raycast-replaced-10-macos-apps.html</guid><pubDate>Mon, 30 Jun 2025 15:51:21 GMT</pubDate></item><item><title>Migrating from Nginx to Caddy</title><link>https://avilpage.com/2025/05/migrating-from-nginx-to-caddy.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When deploying web apps in production, a web server is essential for serving static files, handling reverse proxying, 
and managing SSL/TLS certificates. &lt;/p&gt;
&lt;p&gt;I have been using Nginx for a long time, but I have recently switched to Caddy as it provides automatic HTTPS by default.
In addition, Caddy has a simpler configuration syntax and is easier to set up for basic use cases.&lt;/p&gt;
&lt;h4&gt;Nginx vs Caddy&lt;/h4&gt;
&lt;p&gt;To illustrate the differences, here are some examples of how to configure a simple web server in both Nginx and Caddy.&lt;/p&gt;
&lt;h5&gt;Nginx Configuration&lt;/h5&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;avilpage.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With Nginx, you need to manually handle SSL/TLS certificates, which can be cumbersome. 
You typically use tools like Certbot to obtain and renew certificates.&lt;/p&gt;
&lt;h5&gt;Caddy Configuration&lt;/h5&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;file_server&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;reverse_proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Caddy automatically manages SSL/TLS certificates for you, so you don't need to worry about obtaining or renewing them.
It also provides default redirection from HTTP to HTTPS, making it easier to secure your site.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Caddy's automatic HTTPS and simpler configuration syntax make it a compelling choice for web servers, 
especially for those who want to get started quickly without dealing with the complexities of SSL/TLS management.&lt;/p&gt;</description><category>automation</category><category>devops</category><guid>https://avilpage.com/2025/05/migrating-from-nginx-to-caddy.html</guid><pubDate>Fri, 30 May 2025 15:51:21 GMT</pubDate></item><item><title>Python UV in 100 seconds</title><link>https://avilpage.com/2025/04/learn-python-uv-in-100-seconds.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;UV is a fast Python package manager that replaces tools like pip, pyenv, virtualenv, etc.&lt;/p&gt;
&lt;h4&gt;Install uv&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# On macOS and Linux.&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-LsSf&lt;span class="w"&gt; &lt;/span&gt;https://astral.sh/uv/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
&lt;span class="c1"&gt;# On Windows.&lt;/span&gt;
powershell&lt;span class="w"&gt; &lt;/span&gt;-ExecutionPolicy&lt;span class="w"&gt; &lt;/span&gt;ByPass&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"irm https://astral.sh/uv/install.ps1 | iex"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Installing Python&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;uv&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;list

uv&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.13
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This makes it easy to install and manage multiple versions of Python on your system without needing of &lt;code&gt;pyenv&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Using UV with existing requirements.txt&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;uv&lt;span class="w"&gt; &lt;/span&gt;venv&lt;span class="w"&gt; &lt;/span&gt;--seed&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.13

&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.venv/bin/activate

uv&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is way faster than using any other tool to create virtual environments.&lt;/p&gt;
&lt;h4&gt;Managing virtual environments&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;uv&lt;span class="w"&gt; &lt;/span&gt;init&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.13&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;demo

uv&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;pandas
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This creates a new virtual environment named &lt;code&gt;demo&lt;/code&gt; with Python 3.13 and adds the &lt;code&gt;pandas&lt;/code&gt; package to it.&lt;/p&gt;
&lt;h4&gt;Runs scripts with inline dependencies&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# /// script&lt;/span&gt;
&lt;span class="c1"&gt;# requires-python = "&amp;gt;=3.13"&lt;/span&gt;
&lt;span class="c1"&gt;# dependencies = [&lt;/span&gt;
&lt;span class="c1"&gt;#     "requests",&lt;/span&gt;
&lt;span class="c1"&gt;# ]&lt;/span&gt;
&lt;span class="c1"&gt;# ///&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://avilpage.com"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;uv&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;script.py
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;uvx&lt;/h4&gt;
&lt;p&gt;Similar to &lt;code&gt;pipx&lt;/code&gt;, it can install and run Python applications in isolated environments.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;uv&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;glances

uv&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;glances

&lt;span class="c1"&gt;# shortcut&lt;/span&gt;
uvx&lt;span class="w"&gt; &lt;/span&gt;glances
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;UV speeds up Python development by providing a fast package manager, virtual environment management, and inline dependency management. It is a great alternative to traditional tools like pip, pyenv, and virtualenv.&lt;/p&gt;</description><category>python</category><category>uv</category><guid>https://avilpage.com/2025/04/learn-python-uv-in-100-seconds.html</guid><pubDate>Wed, 30 Apr 2025 17:46:24 GMT</pubDate></item><item><title>Autoscale k8s pods with queue size (KEDA)</title><link>https://avilpage.com/2025/03/autoscale-k8s-pods-with-queue-size-keda.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img alt="keda-postgreql-scaling" src="https://avilpage.com/images/keda-postgresql-scaling1.png"&gt;&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Kubernetes(k8s) is a popular container orchestration tool, and it provides Horizontal Pod Autoscaler(HPA) to scale pods based on CPU and Memory usage. &lt;/p&gt;
&lt;p&gt;To scale pods based on the queue size we can use &lt;a href="https://keda.sh/"&gt;KEDA&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Setup&lt;/h4&gt;
&lt;p&gt;For this demo, we will use PostgreSQL table to store tasks and KEDA to scale the pods based on the queue size.&lt;/p&gt;
&lt;p&gt;As written earlier, we can use k3d and &lt;a href="https://avilpage.com/2025/03/autoscale-k8s-pods-with-queue-size-keda.html"&gt;setup k8s cluster with a single command&lt;/a&gt; anywhere.&lt;/p&gt;
&lt;p&gt;Once the cluster is up, we can set up a simple shell script to produce and consume tasks from the PostgreSQL table.&lt;/p&gt;
&lt;p&gt;I am adding only relevant snippets here. You can find the complete code in the &lt;a href="https://github.com/AvilPage/keda-postgresql-demo"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;PostgreSQL deployment:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres-deployment&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:13&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Producer shell script:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

psql&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;-EOSQL&lt;/span&gt;
&lt;span class="s"&gt;  CREATE TABLE IF NOT EXISTS tasks (&lt;/span&gt;
&lt;span class="s"&gt;      id SERIAL PRIMARY KEY,&lt;/span&gt;
&lt;span class="s"&gt;      description TEXT NOT NULL,&lt;/span&gt;
&lt;span class="s"&gt;      status TEXT NOT NULL&lt;/span&gt;
&lt;span class="s"&gt;  );&lt;/span&gt;
&lt;span class="s"&gt;EOSQL&lt;/span&gt;

&lt;span class="c1"&gt;# Continuously insert tasks&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;true&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;psql&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;-EOSQL&lt;/span&gt;
&lt;span class="s"&gt;    INSE&lt;/span&gt;RT&lt;span class="w"&gt; &lt;/span&gt;INTO&lt;span class="w"&gt; &lt;/span&gt;tasks&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;description,&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;VALUES&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'$DESCRIPTION'&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'$STATUS'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Producer dockerfile:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;postgres:13&lt;/span&gt;

&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;curl

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;producer.sh&lt;span class="w"&gt; &lt;/span&gt;/producer.sh

&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;/producer.sh

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/producer.sh"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Producer deployment:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;task-producer&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;task-producer&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Never&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Consumer shell script:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;TASK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;psql&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;-EOSQL&lt;/span&gt;
&lt;span class="s"&gt;  SELECT id, description, status FROM tasks&lt;/span&gt;
&lt;span class="s"&gt;  WHERE status != 'Completed'&lt;/span&gt;
&lt;span class="s"&gt;  ORDER BY id&lt;/span&gt;
&lt;span class="s"&gt;  LIMIT 1;&lt;/span&gt;
&lt;span class="s"&gt;EOSQL&lt;/span&gt;

&lt;span class="nv"&gt;TASK_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TASK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{print $1}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

psql&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;-EOSQL&lt;/span&gt;
&lt;span class="s"&gt;  UPDATE tasks&lt;/span&gt;
&lt;span class="s"&gt;  SET status = 'Completed'&lt;/span&gt;
&lt;span class="s"&gt;  WHERE id = $TASK_ID;&lt;/span&gt;
&lt;span class="s"&gt;EOSQL&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Consumer dockerfile:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;postgres:13&lt;/span&gt;

&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;bash

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;consumer.sh&lt;span class="w"&gt; &lt;/span&gt;/consumer.sh

&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;/consumer.sh

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/consumer.sh"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Consumer deployment:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;task-consumer&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;task-consumer&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Never&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of pushing these images to any container registry, we can directly load the images into cluster using &lt;code&gt;k3d image&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;k3d&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;task-producer&lt;span class="w"&gt; &lt;/span&gt;--cluster&lt;span class="w"&gt; &lt;/span&gt;demo-cluster
k3d&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;task-consumer&lt;span class="w"&gt; &lt;/span&gt;--cluster&lt;span class="w"&gt; &lt;/span&gt;demo-cluster
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After that, we can deploy postgres, consumer and producer using the above deployment files.&lt;/p&gt;
&lt;p&gt;Once the deployment is done, we can monitor the tasks from pod logs.&lt;/p&gt;
&lt;p&gt;Lets install KEDA in the cluster and setup a scaled-object to scale the consumer pods based on number of pending tasks.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;helm&lt;span class="w"&gt; &lt;/span&gt;repo&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;kedacore&lt;span class="w"&gt; &lt;/span&gt;https://kedacore.github.io/charts
helm&lt;span class="w"&gt; &lt;/span&gt;repo&lt;span class="w"&gt; &lt;/span&gt;update
helm&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;keda&lt;span class="w"&gt; &lt;/span&gt;kedacore/keda&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ScaledObject:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;keda.sh/v1alpha1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ScaledObject&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;task-consumer-scaler&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;task-consumer&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pollingInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cooldownPeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;minReplicaCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;maxReplicaCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;50&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;triggers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgresql&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres-service&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"SELECT&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;COUNT(*)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;FROM&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;WHERE&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Completed';"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;targetQueryValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this, KEDA will scale the consumer pods based on the number of tasks in the PostgreSQL table. The &lt;code&gt;targetQueryValue&lt;/code&gt; is set to 10, which means if there are more than 10 tasks in the table, KEDA will scale up the consumer pods.&lt;/p&gt;
&lt;p&gt;In the cluster, after a while, a bunch of tasks will be created in the PostgreSQL table. Now, we can set the status of all tasks to empty so that we can see auto-scaling in action.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;task-producer-&amp;lt;pod-id&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;psql&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;-EOSQL&lt;/span&gt;
&lt;span class="s"&gt;  UPDATE tasks&lt;/span&gt;
&lt;span class="s"&gt;  SET status = '';&lt;/span&gt;
&lt;span class="s"&gt;EOSQL&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On k8s dashboard, we can see the consumer pods scaling up and down based on the number of tasks in the PostgreSQL table.&lt;/p&gt;
&lt;p&gt;&lt;img alt="keda-postgreql-scaling" src="https://avilpage.com/images/keda-postgresql-scaling.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;KEDA is a powerful tool to scale k8s pods based on custom metrics. In this post, we have used PostgreSQL but we can use KEDA with variety of other data stores as well. Full code for this post is &lt;a href="https://github.com/AvilPage/keda-postgresql-demo"&gt;available here&lt;/a&gt;.&lt;/p&gt;</description><category>kubernetes</category><guid>https://avilpage.com/2025/03/autoscale-k8s-pods-with-queue-size-keda.html</guid><pubDate>Thu, 27 Mar 2025 06:07:52 GMT</pubDate></item><item><title>Free DockerHub Alternative - ECR Public Gallery</title><link>https://avilpage.com/2025/02/free-dockerhub-alternative-ecr-gallery.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img alt="docker-rate-limits" src="https://avilpage.com/images/docker-rate-limits.png"&gt;&lt;/p&gt;
&lt;p&gt;DockerHub started rate limiting&lt;sup id="fnref:rate"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2025/02/free-dockerhub-alternative-ecr-gallery.html#fn:rate"&gt;1&lt;/a&gt;&lt;/sup&gt; anonymous docker pulls. When testing out a new CI/CD setup, I hit the rate limit and had to wait for an hour to pull the image. This was a good time to look for alternatives.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gallery.ecr.aws/"&gt;AWS ECR Public Gallery&lt;/a&gt;&lt;sup id="fnref:ecr"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2025/02/free-dockerhub-alternative-ecr-gallery.html#fn:ecr"&gt;2&lt;/a&gt;&lt;/sup&gt; is a good alternative to DockerHub as of today(2025 Feb). It is free and does not have rate limits even for anonymous users. &lt;/p&gt;
&lt;p&gt;&lt;img alt="public-ecr-gallery" src="https://avilpage.com/images/public-ecr-gallery.png"&gt;&lt;/p&gt;
&lt;p&gt;Once we find the required image from the gallery, we can simply change the image name in the &lt;code&gt;docker pull&lt;/code&gt; command to pull the image from ECR Gallery.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;docker&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;public.ecr.aws/ubuntu/ubuntu
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;Dockerfile&lt;/code&gt;, we can use the image from ECR Gallery as follows:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;public.ecr.aws/ubuntu/ubuntu&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is a quick way to avoid DockerHub rate limits.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:rate"&gt;
&lt;p&gt;&lt;a href="https://docs.docker.com/docker-hub/usage/"&gt;DockerHub Limits&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2025/02/free-dockerhub-alternative-ecr-gallery.html#fnref:rate" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ecr"&gt;
&lt;p&gt;&lt;a href="https://gallery.ecr.aws"&gt;AWS ECR Public Gallery&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2025/02/free-dockerhub-alternative-ecr-gallery.html#fnref:ecr" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>docker</category><guid>https://avilpage.com/2025/02/free-dockerhub-alternative-ecr-gallery.html</guid><pubDate>Sun, 09 Feb 2025 16:08:34 GMT</pubDate></item><item><title>Postman - Auto Login &amp; Renew OAuth2 Token</title><link>https://avilpage.com/2025/01/postman-auto-login-renew-oauth2-token.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When using Postman to interact with APIs behind an OAuth2 authentication, we need to login and renew the token manually. This can be automated using the following steps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set credentials in environment variables&lt;/li&gt;
&lt;li&gt;Create a pre-request script to login and renew the token&lt;/li&gt;
&lt;li&gt;Use the token in the request headers&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Automating Login &amp;amp; Renewal&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isSessionExpired&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loginTimestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"loginTimestamp"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expiresInSeconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"expiresInSeconds"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginTimestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loginDuration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loginTimestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;isSessionExpired&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loginDuration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expiresInSeconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSessionExpired&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/auth/connect/token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'application/x-www-form-urlencoded'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s1"&gt;'Accept'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'application/json'&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'urlencoded'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;urlencoded&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"grant_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"client_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"client_id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;jsonData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"access_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;jsonData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;expires_in&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;expiresInSeconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;expires_in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"expiresInSeconds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expiresInSeconds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"loginTimestamp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can copy this script to the pre-request script of the collection. &lt;/p&gt;
&lt;p&gt;&lt;img alt="Cockpit" src="https://avilpage.com/images/postman-auto-login.png"&gt;&lt;/p&gt;
&lt;p&gt;Most of the script is self-explanatory. The script checks if the session is expired and sends a request to the token endpoint to get a new token. The token is stored in environment variables and used in the request headers.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;This is a one time setup for Postman collection and it saves a lot of time in the long run. The script can be modified to handle different grant types and token renewal strategies.&lt;/p&gt;</description><category>automation</category><category>postman</category><guid>https://avilpage.com/2025/01/postman-auto-login-renew-oauth2-token.html</guid><pubDate>Fri, 31 Jan 2025 17:20:17 GMT</pubDate></item><item><title>Install Cockpit on Remote Linux VM</title><link>https://avilpage.com/2024/12/install-cockpit-on-remote-linux-vm.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;&lt;img alt="Cockpit" src="https://avilpage.com/images/cockpit-how-to.png"&gt;&lt;/p&gt;
&lt;p&gt;Cockpit is an easy to use web-based interface(like a cPanel) for managing Linux servers. When we want to provide access to non-developers or people who are new to linux, it is a good idea to get them started with Cockpit. It provides a user-friendly interface to manage services, containers, storage, logs, and more.&lt;/p&gt;
&lt;h4&gt;Setup&lt;/h4&gt;
&lt;p&gt;Let's create a new Ubuntu VM and install Cockpit on it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
.&lt;span class="w"&gt; &lt;/span&gt;/etc/os-release
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION_CODENAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;-backports&lt;span class="w"&gt; &lt;/span&gt;cockpit
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the installation is complete, we can get the public ip of the VM and access the Cockpit web interface running on port 9090.&lt;/p&gt;
&lt;p&gt;It will be difficult to remember the public ip of the VM. So, let's create a DNS record for the VM. Let's add an &lt;code&gt;A&lt;/code&gt; record in DNS settings to point &lt;code&gt;cockpit.avilpage.com&lt;/code&gt; to the public ip of the VM.&lt;/p&gt;
&lt;h4&gt;Reverse Proxy&lt;/h4&gt;
&lt;p&gt;Let's set up a reverse proxy to access the Cockpit web interface using a subdomain.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;caddy
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add the below configuration to &lt;code&gt;/etc/caddy/Caddyfile&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;cockpit.avilpage.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;reverse_proxy&lt;span class="w"&gt; &lt;/span&gt;localhost:9090
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We need &lt;code&gt;Origins&lt;/code&gt; to Cockpit configuration at &lt;code&gt;/etc/cockpit/cockpit.conf&lt;/code&gt; to allow requests from the subdomain.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;[&lt;/span&gt;WebService&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;Origins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;https://cockpit.avilpage.com
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart both services and open &lt;a href="https://cockpit.avilpage.com"&gt;https://cockpit.avilpage.com&lt;/a&gt; in browser.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;cockpit
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;caddy
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Cockpit web UI is a great tool to manage Linux servers even for non-developers. Users can browse/manage logs, services, etc. It also provides a terminal to run commands on the server&lt;/p&gt;</description><category>linux</category><category>productivity</category><guid>https://avilpage.com/2024/12/install-cockpit-on-remote-linux-vm.html</guid><pubDate>Mon, 30 Dec 2024 22:54:07 GMT</pubDate></item><item><title>Mastering "Partial Covered Calls" - Part 1</title><link>https://avilpage.com/2024/11/mastering-partial-covered-calls.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Covered Calls&lt;/h4&gt;
&lt;p&gt;In a covered call strategy, we buy one lot of stocks (or 1 Future) and sell at the money call option. The payoff diagram looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Covered Call" src="https://avilpage.com/images/covered-call.png"&gt;&lt;/p&gt;
&lt;p&gt;There are 2 drawbacks of this strategy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It requires a lot of capital to buy the shares. We can't fully use the margin from pledging the stocks.&lt;/li&gt;
&lt;li&gt;We need to sell the stocks at expiry if stock price closes above the strike price.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To overcome this limitation, we can use a strategy called "partial covered calls."&lt;/p&gt;
&lt;h4&gt;Partial Covered Calls&lt;/h4&gt;
&lt;p&gt;Instead of buying one lot of shares, we can buy "partial" or "fractional" lot of shares and then sell a far away call option instead of at the money call option. &lt;/p&gt;
&lt;p&gt;For example, we can buy 0.15 lot of shares and sell a call option which is 10% away from the current price. The payoff diagram looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Partial Covered Call" src="https://avilpage.com/images/partial-covered-call.png"&gt;&lt;/p&gt;
&lt;p&gt;Here we can pledge the stocks we have bought and use the margin to sell call option using that margin.&lt;/p&gt;
&lt;p&gt;Since we are selling a call option which is far away from the current price, the probability of the call option getting exercised is very low. So we can keep the premium we received from selling the call option.&lt;/p&gt;
&lt;p&gt;In addition to that, we get the long term capital appreciation of the stocks we have bought and there won't be short term capital gains tax on them.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;If you want to hold the stock for long but still want to generate regular income from it, then partial covered calls is a good strategy to consider.&lt;/p&gt;</description><category>fno</category><category>partial-covered-calls</category><category>trading</category><guid>https://avilpage.com/2024/11/mastering-partial-covered-calls.html</guid><pubDate>Sat, 30 Nov 2024 06:52:10 GMT</pubDate></item><item><title>Cube &amp; Cubicle</title><link>https://avilpage.com/2024/10/cube-cubicle.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Rubiks Cube&lt;/h4&gt;
&lt;p&gt;When I was in college, I was traveling to a friend's place and missed bus at midnight. The next bus was at 4 AM. While I was bored waiting for the bus, I found Rubik's Cube in a shop.&lt;/p&gt;
&lt;p&gt;I scrambled the cube and spent the next 4 hours trying to solve the cube. I managed to solve one color. When I tried to solve the next color, the pieces in the previous layer started missing.&lt;/p&gt;
&lt;p&gt;Even after spending a lot of time in the next 3 weeks, I couldn't solve it and gave up.&lt;/p&gt;
&lt;p&gt;After a couple of years, when I "learnt" about the internet, I searched and found simple algorithms to solve the cube. Within a few days, I was able to solve the cube in a minute.&lt;/p&gt;
&lt;h4&gt;Office Cubicles&lt;/h4&gt;
&lt;p&gt;In the final year of college, there were placements. When I was preparing resume, I included "I can solve Rubik's Cube in a minute" in it.&lt;/p&gt;
&lt;p&gt;During the interview, interviewer asked me if I can really solve the cube in a minute. He asked me to get my cube and show him during the lunch break. I did.
Luckily, I got hired.&lt;/p&gt;
&lt;p&gt;Even though, I was hired for Wipro I didn't join. I went to Bangalore and started applying for start-up jobs.&lt;/p&gt;
&lt;p&gt;I went for an interview at a web development company in Malleswaram, Bangalore. The CEO looked at my résumé, took out a cube from his desk. He handed the cube to me, showed an empty cubicle behind me and said, "If you solve the cube in a minute, that cubicle is yours."&lt;/p&gt;
&lt;p&gt;Just by learning the cube, I was able to land a job an at an MNC(Multi National Company) and a startup as well.&lt;/p&gt;</description><category>musings</category><category>rubiks-cube</category><guid>https://avilpage.com/2024/10/cube-cubicle.html</guid><pubDate>Thu, 31 Oct 2024 03:35:37 GMT</pubDate></item><item><title>tailscale: Resolving CGNAT (100.x.y.z) Conflicts</title><link>https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In an earlier blog post, I wrote about using tailscale to remotely access any device&lt;sup id="fnref:ap"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fn:ap"&gt;1&lt;/a&gt;&lt;/sup&gt;. Tailscale uses 100.64.0.0/10 subnet&lt;sup id="fnref:ts100"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fn:ts100"&gt;2&lt;/a&gt;&lt;/sup&gt; to assign unique IP addresses to each device.&lt;/p&gt;
&lt;p&gt;When a tailscale node joins another campus network&lt;sup id="fnref:pn"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fn:pn"&gt;3&lt;/a&gt;&lt;/sup&gt; (schools, universities, offices) that uses the same subnet, it will face conflicts. Let's see how to resolve this.&lt;/p&gt;
&lt;h4&gt;Private Network&lt;/h4&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/tailscale-cgnat2.png" alt="tailscale dashboard"&gt;&lt;/p&gt;
&lt;p&gt;In the above scenario, node C1 will be able to connect C2 &amp;amp; C3 as they are in the same network.&lt;/p&gt;
&lt;p&gt;Once we start tailscale on node C1, it will get a 100.x.y.z IP address from tailscale subnet. Now, node C1 will not be able to connect to node C2 &amp;amp; C3.&lt;/p&gt;
&lt;p&gt;To avoid conflicts with the existing network, we can configure tailscale to use a "smaller" subnet using "ipPool".&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"acls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"nodeAttrs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;"autogroup:admin"&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"ipPool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;"100.100.96.0/20"&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once it is configured, taiscale will start assigning IP addresses from the new subnet. Even though ip address allocation is limited, we can't still access nodes in other subnets due to a bug&lt;sup id="fnref:tsb"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fn:tsb"&gt;5&lt;/a&gt;&lt;/sup&gt; in tailscale.&lt;/p&gt;
&lt;p&gt;As a workaround, we can manually update the iptables to route traffic to the correct subnet.&lt;/p&gt;
&lt;p&gt;Lets look at the iptables rules added by tailscale by stopping it and then starting it.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/tailscale-cgnat3.png" alt="tailscale iptables rules"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/tailscale-cgnat4.png" alt="tailscale iptables rules"&gt;&lt;/p&gt;
&lt;p&gt;The highlighted rule drops any incoming packet that doesn't originate from tailscale0 interface, and source IP is 100.64.0.0/10 (100.64.0.0 to 100.127.255.255).&lt;/p&gt;
&lt;p&gt;Let's delete this rule and add a new rule to restrict the source IP to 100.100.96.0/20 (100.100.96.1 to 100.100.111.254).&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;--delete&lt;span class="w"&gt; &lt;/span&gt;ts-input&lt;span class="w"&gt; &lt;/span&gt;--source&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;.64.0.0/10&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;tailscale0&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;DROP
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;--insert&lt;span class="w"&gt; &lt;/span&gt;ts-input&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--source&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;.100.96.0/20&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;tailscale0&lt;span class="w"&gt; &lt;/span&gt;-j&lt;span class="w"&gt; &lt;/span&gt;DROP
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src="https://avilpage.com/images/tailscale-cgnat5.png" alt="tailscale iptables rules"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;By configuring tailscale to use a smaller subnet, we can avoid conflicts with existing networks. Even though there is a bug in tailscale, we can manually update iptables to route traffic to the correct subnet.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:ap"&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2023/09/tailscale-remote-ssh-raspberry-pi.html"&gt;tailscale: Remotely access any device&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fnref:ap" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ts100"&gt;
&lt;p&gt;&lt;a href="https://tailscale.com/kb/1015/100.x-addresses"&gt;https://tailscale.com/kb/1015/100.x-addresses&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fnref:ts100" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:pn"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Private_network"&gt;https://en.wikipedia.org/wiki/Private_network&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fnref:pn" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ip"&gt;
&lt;p&gt;&lt;a href="https://tailscale.com/kb/1304/ip-pool"&gt;https://tailscale.com/kb/1304/ip-pool&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fnref:ip" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:tsb"&gt;
&lt;p&gt;&lt;a href="https://github.com/tailscale/tailscale/issues/1381"&gt;https://github.com/tailscale/tailscale/issues/1381&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html#fnref:tsb" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>networking</category><category>tailscale</category><guid>https://avilpage.com/2024/09/tailscale-cgnat-conflicts-resolution.html</guid><pubDate>Sat, 07 Sep 2024 07:20:05 GMT</pubDate></item><item><title>Mastering Kraken2 - Part 4 - Build FDA-ARGOS Index</title><link>https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Mastering Kraken2&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html"&gt;Part 1 - Initial Runs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html"&gt;Part 2 - Classification Performance Optimisation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html"&gt;Part 3 - Build custom database indices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html"&gt;Part 4 - Build FDA-ARGOS index&lt;/a&gt; (this post)&lt;/p&gt;
&lt;p&gt;Part 5 - Regular vs Fast Builds (upcoming)&lt;/p&gt;
&lt;p&gt;Part 6 - Benchmarking (upcoming)&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In the previous post, we learnt how to build a custom index for Kraken2.&lt;/p&gt;
&lt;p&gt;FDA-ARGOS&lt;sup id="fnref:argos"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html#fn:argos"&gt;1&lt;/a&gt;&lt;/sup&gt; is a popular database with quality reference genomes for diagnostic usage. Let's build an index for FDA-ARGOS.&lt;/p&gt;
&lt;h4&gt;FDA-ARGOS Kraken2 Index&lt;/h4&gt;
&lt;p&gt;FDA-ARGOS db is available at NCBI&lt;sup id="fnref:ncbi"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html#fn:ncbi"&gt;2&lt;/a&gt;&lt;/sup&gt; from which we can download the assembly file.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/fda-argos-kraken2-index.png" alt="FDA-ARGOS NCBI" class="img-fluid"&gt;&lt;/p&gt;
&lt;p&gt;We can extract accession numbers from the assembly file and then download the genomes from these accession ids.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^#"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;PRJNA231221_AssemblyDetails.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="s1"&gt;$'\t'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f1&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;accessions.txt

$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;accessions.txt
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1428&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1428&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22848&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;accessions.txt

$&lt;span class="w"&gt; &lt;/span&gt;ncbi-genome-download&lt;span class="w"&gt; &lt;/span&gt;--section&lt;span class="w"&gt; &lt;/span&gt;genbank&lt;span class="w"&gt; &lt;/span&gt;--assembly-accessions&lt;span class="w"&gt; &lt;/span&gt;accessions.txt&lt;span class="w"&gt; &lt;/span&gt;--progress-bar&lt;span class="w"&gt; &lt;/span&gt;bacteria&lt;span class="w"&gt; &lt;/span&gt;--parallel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It took ~8 minutes to download all the genomes, and the downloaded file size is ~4GB.&lt;/p&gt;
&lt;p&gt;We can use kraken-db-builder&lt;sup id="fnref:kdb"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html#fn:kdb"&gt;3&lt;/a&gt;&lt;/sup&gt; tool to build index from these genbank genome files.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# kraken-db-builder needs this to convert gbff to fasta format&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;bioconda&lt;span class="w"&gt; &lt;/span&gt;any2fasta

$&lt;span class="w"&gt; &lt;/span&gt;kraken-db-builder&lt;span class="w"&gt; &lt;/span&gt;--genomes-dir&lt;span class="w"&gt; &lt;/span&gt;genbank&lt;span class="w"&gt; &lt;/span&gt;--threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;36&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--db-name&lt;span class="w"&gt; &lt;/span&gt;k2_argos
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It took ~30 minutes to build the index.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We have built a Kraken2 index for the FDA-ARGOS database on 2024-Aug-24.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ChillarAnand/avilpage.com/tree/master/scripts/kraken2_argos"&gt;FDA-ARGOS Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drive.google.com/file/d/1PbwriW3i3pkXJMFF5nq9OK_EqrwPiLWr/view"&gt;Kraken2 Gzipped Index file&lt;/a&gt; (gzip size: 2.6GB, index size: 3.8GB, md5sum: 1dd946d2e405dfec35ed3e319e9dfeac)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ChillarAnand/avilpage.com/tree/master/scripts/kraken2_argos"&gt;Kraken2 Inspect file&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the next post, we will look at the differences between regular and fast builds.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:argos"&gt;
&lt;p&gt;&lt;a href="https://www.nature.com/articles/s41467-019-11306-6"&gt;https://www.nature.com/articles/s41467-019-11306-6&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html#fnref:argos" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ncbi"&gt;
&lt;p&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/bioproject/231221"&gt;https://www.ncbi.nlm.nih.gov/bioproject/231221&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html#fnref:ncbi" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:kdb"&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/kdb.html"&gt;https://avilpage.com/kdb.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html#fnref:kdb" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>bioinformatics</category><category>kraken2</category><category>metagenomics</category><guid>https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html</guid><pubDate>Sat, 24 Aug 2024 09:58:00 GMT</pubDate></item><item><title>Midnight Coding for Narendra Modi &amp; Ivanka Trump</title><link>https://avilpage.com/2024/08/midnight-coding-narendra-modi-ivanka-trump.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img src="https://avilpage.com/images/midnight-modi-trump.png" alt="GES 2017, modi trump mitra"&gt;&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In 2017, GES Event was held in Hyderabad, India. Narendra Modi (the Prime Minister of India) &amp;amp; Ivanka Trump (daughter of the then US President Donald Trump) were the chief guests.&lt;/p&gt;
&lt;p&gt;At that time, I was part of Invento team, and we decided to develop a new version of Mitra robot for the event.&lt;/p&gt;
&lt;h4&gt;The Challenge&lt;/h4&gt;
&lt;p&gt;We had to develop the new version of Mitra robot in a short span of time. Entire team worked day and night to meet the deadlines and finish the new version.&lt;/p&gt;
&lt;p&gt;We went to Hyderabad from Bangalore a few days before to prepare for the event. We have cleared multiple security checks, did some demos for various people before the event.&lt;/p&gt;
&lt;p&gt;A day before the event, around 9 PM we discovered a critical bug in the software. Due to that bug, the Robot motors were running at full speed which was dangerous. If the robot hits someone at full speed, it could cause serious injuries.&lt;/p&gt;
&lt;p&gt;I spent a few hours debugging the issue and even tried rolling back a few versions. Still, I couldn't pinpoint the issue.&lt;/p&gt;
&lt;p&gt;Since we need only a small set of Robot features, we decided to create a new version of the software with only limited features. I spent the next few hours creating a new release.&lt;/p&gt;
&lt;p&gt;After that, we spent the next few hours doing extensive testing to make sure there are no bugs in the new version.&lt;/p&gt;
&lt;p&gt;It was almost morning by the time we were done with testing. We quickly went to hotel to have some rest and get back early for the event.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Mitra robot welcoming Modi &amp;amp; Trump went very well. You can read about Balaji Viswanathan's experience at GES 2017 on Quora&lt;sup id="fnref:quora"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/08/midnight-coding-narendra-modi-ivanka-trump.html#fn:quora"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/midnight-modi-trump-anand.jpg" alt="GES 2017, modi trump mitra anand"&gt;&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:quora"&gt;
&lt;p&gt;&lt;a href="https://www.quora.com/How-was-Balaji-Viswanathans-overall-experience-attending-the-Global-Entrepreneurship-Summit-2017-held-in-Hyderabad-Where-his-Inventos-Mitra-is-launched"&gt;Answer on Quora&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/08/midnight-coding-narendra-modi-ivanka-trump.html#fnref:quora" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>musings</category><guid>https://avilpage.com/2024/08/midnight-coding-narendra-modi-ivanka-trump.html</guid><pubDate>Sun, 18 Aug 2024 00:25:43 GMT</pubDate></item><item><title>How (and when) to use systemd timer instead of cronjob</title><link>https://avilpage.com/2024/08/guide-systemd-timer-cronjob.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;demo.sh
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just a single line of code is sufficient to schedule a cron job. However, there are some scenarios where I find systemd timer more useful than cronjob.&lt;/p&gt;
&lt;h4&gt;How to use systemd timer&lt;/h4&gt;
&lt;p&gt;We need to create a service file(contains the script to be run) and a timer(contains the schedule).&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# demo.service&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;Unit&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Demo&lt;span class="w"&gt; &lt;/span&gt;service

&lt;span class="o"&gt;[&lt;/span&gt;Service&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;demo.sh
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# demo.timer&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;Unit&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Run&lt;span class="w"&gt; &lt;/span&gt;myscript.service&lt;span class="w"&gt; &lt;/span&gt;every&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;minutes

&lt;span class="o"&gt;[&lt;/span&gt;Timer&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;OnBootSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1min
&lt;span class="nv"&gt;OnUnitActiveSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1min

&lt;span class="o"&gt;[&lt;/span&gt;Install&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;multi-user.target
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can copy these files to &lt;code&gt;/etc/systemd/system/&lt;/code&gt; and enable the timer.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;demo.service&lt;span class="w"&gt; &lt;/span&gt;demo.timer&lt;span class="w"&gt; &lt;/span&gt;/etc/systemd/system/

$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;daemon-reload

$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--now&lt;span class="w"&gt; &lt;/span&gt;demo.timer
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use &lt;code&gt;systemctl&lt;/code&gt; to see when the task is executed last and when it will be executed next.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;list-timers&lt;span class="w"&gt; &lt;/span&gt;--all
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src="https://avilpage.com/images/systemd-timer-cronjob.png" alt="systemd timer"&gt;&lt;/p&gt;
&lt;h4&gt;Use Cases&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Singleton - In the above example, lets say &lt;code&gt;demo.sh&lt;/code&gt; takes ~10 minutes to run. With cron job, in ten minutes we will have 10 instances of &lt;code&gt;demo.sh&lt;/code&gt; running. This is not ideal. With systemd timer, it will ensure only one instance of &lt;code&gt;demo.sh&lt;/code&gt; is running at a time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On demand runs - If we want to test out the script/job, systemd allows us to immediately run it with usual &lt;code&gt;systemctl start demo&lt;/code&gt; without needing to run the script manually.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Timer - With cron, we can run tasks upto a minute precision. Timer can run tasks till &lt;code&gt;second&lt;/code&gt; level precision. &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;[&lt;/span&gt;Timer&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;OnCalendar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;*-*-*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;:30:15
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition to that, we can run tasks based on system events. For example, we can run a script 15 minutes from reboot.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;[&lt;/span&gt;Timer&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;OnBootSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15min
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Systemd timer is a powerful tool that can replace cronjob in many scenarios. It provides more control and flexibility over cronjob. However, cronjob is still a good choice for simple scheduling tasks.&lt;/p&gt;</description><category>automation</category><category>devops</category><guid>https://avilpage.com/2024/08/guide-systemd-timer-cronjob.html</guid><pubDate>Mon, 05 Aug 2024 07:37:50 GMT</pubDate></item><item><title>Mastering Kraken2 - Part 3 - Build Custom Database</title><link>https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Mastering Kraken2&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html"&gt;Part 1 - Initial Runs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html"&gt;Part 2 - Classification Performance Optimisation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html"&gt;Part 3 - Build custom database indices&lt;/a&gt; (this post)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html"&gt;Part 4 - Build FDA-ARGOS index&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Part 5 - Regular vs Fast Builds (upcoming)&lt;/p&gt;
&lt;p&gt;Part 6 - Benchmarking (upcoming)&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In the previous post, we learned how to improve kraken2&lt;sup id="fnref:k2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html#fn:k2"&gt;1&lt;/a&gt;&lt;/sup&gt; classification performance. So far we have downloaded &amp;amp; used pre-built genome indices(databases). &lt;/p&gt;
&lt;p&gt;In this post, let's build a custom database for kraken2. For simplicity, let's use only refseq archaea genomes&lt;sup id="fnref:rag"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html#fn:rag"&gt;2&lt;/a&gt;&lt;/sup&gt; for building the index.&lt;/p&gt;
&lt;h4&gt;Building Custom Database&lt;/h4&gt;
&lt;p&gt;First, we need to download the taxonomy files. We can use the &lt;code&gt;k2&lt;/code&gt; script provided by kraken2.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;k2&lt;span class="w"&gt; &lt;/span&gt;download-taxonomy&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;custom_db
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This takes ~30 minutes depending on the network speed. The taxonomy files are downloaded to the &lt;code&gt;custom_db/taxonomy&lt;/code&gt; directory.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;custom_db/taxonomy
citations.dmp&lt;span class="w"&gt;  &lt;/span&gt;division.dmp&lt;span class="w"&gt;  &lt;/span&gt;gencode.dmp&lt;span class="w"&gt;  &lt;/span&gt;merged.dmp&lt;span class="w"&gt;  &lt;/span&gt;nodes.dmp
nucl_wgs.accession2taxid&lt;span class="w"&gt; &lt;/span&gt;delnodes.dmp&lt;span class="w"&gt;  &lt;/span&gt;gc.prt&lt;span class="w"&gt; &lt;/span&gt;
images.dmp&lt;span class="w"&gt;  &lt;/span&gt;names.dmp&lt;span class="w"&gt;  &lt;/span&gt;nucl_gb.accession2taxid&lt;span class="w"&gt;  &lt;/span&gt;readme.txt

$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-hs&lt;span class="w"&gt; &lt;/span&gt;custom_db/taxonomy
43G&lt;span class="w"&gt;     &lt;/span&gt;custom_db/taxonomy
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For simplicity, let's use the archaea refseq genomes. We can use &lt;code&gt;kraken2-build&lt;/code&gt; to download the refseq genomes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;k2&lt;span class="w"&gt; &lt;/span&gt;download-library&lt;span class="w"&gt; &lt;/span&gt;--library&lt;span class="w"&gt; &lt;/span&gt;archaea&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;custom_db
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This runs on a single thread. Instead of using &lt;code&gt;kraken2-build&lt;/code&gt;, we can use &lt;code&gt;ncbi-genome-download&lt;/code&gt;&lt;sup id="fnref:ngd"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html#fn:ngd"&gt;3&lt;/a&gt;&lt;/sup&gt; tool to download the genomes. This provides much granular control over the download process. For example, we can download only &lt;code&gt;--assembly-levels complete&lt;/code&gt; genomes. We can also download multiple genomes in parallel.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;ncbi-genome-download

$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;bioconda&lt;span class="w"&gt; &lt;/span&gt;ncbi-genome-download

$&lt;span class="w"&gt; &lt;/span&gt;ncbi-genome-download&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;refseq&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;fasta&lt;span class="w"&gt; &lt;/span&gt;--parallel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-P&lt;span class="w"&gt; &lt;/span&gt;archaea
Checking&lt;span class="w"&gt; &lt;/span&gt;assemblies:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;%&lt;span class="p"&gt;|&lt;/span&gt;███&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2184&lt;/span&gt;/2184&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;:19&amp;lt;&lt;span class="m"&gt;00&lt;/span&gt;:00,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;111&lt;/span&gt;.60entries/s&lt;span class="o"&gt;]&lt;/span&gt;
Downloading&lt;span class="w"&gt; &lt;/span&gt;assemblies:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;%&lt;span class="p"&gt;|&lt;/span&gt;███&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2184&lt;/span&gt;/2184&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:04&amp;lt;&lt;span class="m"&gt;00&lt;/span&gt;:00,&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.54s/files&lt;span class="o"&gt;]&lt;/span&gt;
Downloading&lt;span class="w"&gt; &lt;/span&gt;assemblies:&lt;span class="w"&gt; &lt;/span&gt;2184files&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;02&lt;/span&gt;:23,&lt;span class="w"&gt; &lt;/span&gt;2184files/s&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In just 2 minutes, it has downloaded all the files. Lets gunzip the files.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;refseq&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.gz"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-print0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;parallel&lt;span class="w"&gt; &lt;/span&gt;-0&lt;span class="w"&gt; &lt;/span&gt;gunzip

$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-hs&lt;span class="w"&gt; &lt;/span&gt;refseq
&lt;span class="m"&gt;5&lt;/span&gt;.9G&lt;span class="w"&gt;    &lt;/span&gt;refseq
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lets add all fasta genome files to the custom database&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;refseq&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.fna"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;kraken2-build&lt;span class="w"&gt; &lt;/span&gt;--add-to-library&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;custom_db&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="m"&gt;667&lt;/span&gt;.46s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt;.78s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;106&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:54.80&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;kraken2-build&lt;/code&gt; doesn't use multiple threads for adding genomes to the database. In addition to that, it also doesn't check if the genome is already present in the database. &lt;/p&gt;
&lt;p&gt;Let's use &lt;code&gt;k2&lt;/code&gt; for adding genomes to the database.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;KRAKEN_NUM_THREADS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.fna"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;k2&lt;span class="w"&gt; &lt;/span&gt;add-to-library&lt;span class="w"&gt; &lt;/span&gt;--files&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;custom_db&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="m"&gt;668&lt;/span&gt;.37s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;88&lt;/span&gt;.44s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;159&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;:54.40&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This took only half the time compared to &lt;code&gt;kraken2-build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let's build the index from the library.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2-build&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;custom_db&lt;span class="w"&gt; &lt;/span&gt;--build&lt;span class="w"&gt; &lt;/span&gt;--threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;36&lt;/span&gt;
Creating&lt;span class="w"&gt; &lt;/span&gt;sequence&lt;span class="w"&gt; &lt;/span&gt;ID&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;taxonomy&lt;span class="w"&gt; &lt;/span&gt;ID&lt;span class="w"&gt; &lt;/span&gt;map&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;step&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;...
Found&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;/125783&lt;span class="w"&gt; &lt;/span&gt;targets,&lt;span class="w"&gt; &lt;/span&gt;searched&lt;span class="w"&gt; &lt;/span&gt;through&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;accession&lt;span class="w"&gt; &lt;/span&gt;IDs...
Found&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;59923&lt;/span&gt;/125783&lt;span class="w"&gt; &lt;/span&gt;targets,&lt;span class="w"&gt; &lt;/span&gt;searched&lt;span class="w"&gt; &lt;/span&gt;through&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;822105735&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;accession&lt;span class="w"&gt; &lt;/span&gt;IDs,&lt;span class="w"&gt; &lt;/span&gt;search&lt;span class="w"&gt; &lt;/span&gt;complete.
lookup_accession_numbers:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;65860&lt;/span&gt;/125783&lt;span class="w"&gt; &lt;/span&gt;accession&lt;span class="w"&gt; &lt;/span&gt;numbers&lt;span class="w"&gt; &lt;/span&gt;remain&lt;span class="w"&gt; &lt;/span&gt;unmapped,&lt;span class="w"&gt; &lt;/span&gt;see&lt;span class="w"&gt; &lt;/span&gt;unmapped.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DB&lt;span class="w"&gt; &lt;/span&gt;directory
Sequence&lt;span class="w"&gt; &lt;/span&gt;ID&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;taxonomy&lt;span class="w"&gt; &lt;/span&gt;ID&lt;span class="w"&gt; &lt;/span&gt;map&lt;span class="w"&gt; &lt;/span&gt;complete.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;2m1.950s&lt;span class="o"&gt;]&lt;/span&gt;
Estimating&lt;span class="w"&gt; &lt;/span&gt;required&lt;span class="w"&gt; &lt;/span&gt;capacity&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;step&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;...
Estimated&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;table&lt;span class="w"&gt; &lt;/span&gt;requirement:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5340021028&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bytes
Capacity&lt;span class="w"&gt; &lt;/span&gt;estimation&lt;span class="w"&gt; &lt;/span&gt;complete.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;23&lt;/span&gt;.875s&lt;span class="o"&gt;]&lt;/span&gt;
Building&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;files&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;step&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;...
Taxonomy&lt;span class="w"&gt; &lt;/span&gt;parsed&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;converted.
CHT&lt;span class="w"&gt; &lt;/span&gt;created&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bits&lt;span class="w"&gt; &lt;/span&gt;reserved&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;taxid.
Completed&lt;span class="w"&gt; &lt;/span&gt;processing&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;59911&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3572145823&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bp
Writing&lt;span class="w"&gt; &lt;/span&gt;data&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;disk...&lt;span class="w"&gt;  &lt;/span&gt;complete.
Database&lt;span class="w"&gt; &lt;/span&gt;files&lt;span class="w"&gt; &lt;/span&gt;completed.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;12m3.368s&lt;span class="o"&gt;]&lt;/span&gt;
Database&lt;span class="w"&gt; &lt;/span&gt;construction&lt;span class="w"&gt; &lt;/span&gt;complete.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Total:&lt;span class="w"&gt; &lt;/span&gt;14m29.666s&lt;span class="o"&gt;]&lt;/span&gt;
kraken2-build&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;custom_db&lt;span class="w"&gt; &lt;/span&gt;--build&lt;span class="w"&gt; &lt;/span&gt;--threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;36&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;24534&lt;/span&gt;.98s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt;.50s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2831&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;:29.75&lt;span class="w"&gt; &lt;/span&gt;total

$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-ll
.rw-rw-r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.3G&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;hash.k2d
drwxrwxr-x&lt;span class="w"&gt;    &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:32&lt;span class="w"&gt; &lt;/span&gt;library
.rw-rw-r--&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:35&lt;span class="w"&gt; &lt;/span&gt;opts.k2d
.rw-rw-r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.5M&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;seqid2taxid.map
.rw-rw-r--&lt;span class="w"&gt; &lt;/span&gt;115k&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:23&lt;span class="w"&gt; &lt;/span&gt;taxo.k2d
lrwxrwxrwx&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:31&lt;span class="w"&gt; &lt;/span&gt;taxonomy
.rw-rw-r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.2M&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Aug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:22&lt;span class="w"&gt; &lt;/span&gt;unmapped.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We are able to build index for ~6GB input files in ~15 minutes.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We learnt some useful tips to speed up the custom database creation process. In the next post, we will learn about regular vs. fast builds.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:k2"&gt;
&lt;p&gt;&lt;a href="https://ccb.jhu.edu/software/kraken2/"&gt;Kraken2&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html#fnref:k2" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:rag"&gt;
&lt;p&gt;&lt;a href="https://ftp.ncbi.nlm.nih.gov/genomes/refseq/archaea/"&gt;RefSeq Archaea genomes&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html#fnref:rag" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ngd"&gt;
&lt;p&gt;&lt;a href="https://github.com/kblin/ncbi-genome-download"&gt;https://github.com/kblin/ncbi-genome-download&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html#fnref:ngd" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>bioinformatics</category><category>kraken2</category><category>metagenomics</category><guid>https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html</guid><pubDate>Thu, 01 Aug 2024 05:22:30 GMT</pubDate></item><item><title>Mastering Kraken2 - Part 2 - Performance Optimisation</title><link>https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Mastering Kraken2&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html"&gt;Part 1 - Initial Runs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html"&gt;Part 2 - Classification Performance Optimisation&lt;/a&gt; (this post)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html"&gt;Part 3 - Build custom database indices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html"&gt;Part 4 - Build FDA-ARGOS index&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Part 5 - Regular vs Fast Builds (upcoming)&lt;/p&gt;
&lt;p&gt;Part 6 - Benchmarking (upcoming)&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In the previous post, we learned how to set up kraken2&lt;sup id="fnref:k2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fn:k2"&gt;1&lt;/a&gt;&lt;/sup&gt;, download pre-built indices, and run kraken2. In this post, we will learn various ways to speed up the classification process.&lt;/p&gt;
&lt;h4&gt;Increasing RAM&lt;/h4&gt;
&lt;p&gt;Kraken2 standard database is ~80GB in size. It is recommended to have at least db size RAM to run kraken2 efficiently&lt;sup id="fnref:ksr"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fn:ksr"&gt;2&lt;/a&gt;&lt;/sup&gt;. Let's use 128GB RAM machine and run kraken2 with ERR10359977&lt;sup id="fnref:err"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fn:err"&gt;3&lt;/a&gt;&lt;/sup&gt; sample.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;ERR10359977.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="m"&gt;95064&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;.35&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.142s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2662&lt;/span&gt;.9&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;402&lt;/span&gt;.02&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;94816&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;99&lt;/span&gt;.74%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;248&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.26%&lt;span class="o"&gt;)&lt;/span&gt;
kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;ERR10359977.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.68s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;152&lt;/span&gt;.19s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;35&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;:17.55&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the time taken has come down from 40 minutes to 7 minutes. The classification speed has also increased from 0.19 Mbp/m to 402.02 Mbp/m.&lt;/p&gt;
&lt;p&gt;The previous sample had only a few reads, and the speed is not a good indicator. Let's run kraken2 with a larger sample.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
Processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14980000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2972330207&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;span class="m"&gt;17121245&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3397&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;797&lt;/span&gt;.424s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1288&lt;/span&gt;.2&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;.61&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9826671&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;57&lt;/span&gt;.39%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;7294574&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;.61%&lt;span class="o"&gt;)&lt;/span&gt;
kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;526&lt;/span&gt;.39s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;308&lt;/span&gt;.24s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;68&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:23.86&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This took almost 20 minutes to classify ~3 Gbp of data. Out of 20 minutes, 13 minutes was spent in classification. The remaining time in loading the db into memory.&lt;/p&gt;
&lt;p&gt;Let's use k2_plusPF&lt;sup id="fnref:k2p"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fn:k2p"&gt;4&lt;/a&gt;&lt;/sup&gt; db, which is twice the size of k2_standard and run kraken2.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_plusfp&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...done.
&lt;span class="m"&gt;17121245&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3397&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;755&lt;/span&gt;.290s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1360&lt;/span&gt;.1&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;269&lt;/span&gt;.87&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9903824&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;57&lt;/span&gt;.85%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;7217421&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;.15%&lt;span class="o"&gt;)&lt;/span&gt;
kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_plusfp/&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt;  &lt;/span&gt;&amp;gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;509&lt;/span&gt;.71s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;509&lt;/span&gt;.51s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;:35.49&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This took ~30 minutes to complete, but the classification took only 13 minutes similar to k2_standard. The remaining time was spent in loading the db into memory.&lt;/p&gt;
&lt;h4&gt;Preloading db into RAM&lt;/h4&gt;
&lt;p&gt;We can use vmtouch&lt;sup id="fnref:vmt"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fn:vmt"&gt;5&lt;/a&gt;&lt;/sup&gt; to preload db into RAM. kraken2 provides &lt;code&gt;--memory-mapping&lt;/code&gt; option to use preloaded db. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;vmtouch&lt;span class="w"&gt; &lt;/span&gt;-vt&lt;span class="w"&gt; &lt;/span&gt;k2_standard/hash.k2d&lt;span class="w"&gt; &lt;/span&gt;k2_standard/opts.k2d&lt;span class="w"&gt; &lt;/span&gt;k2_standard/taxo.k2d
&lt;span class="w"&gt;           &lt;/span&gt;Files:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;Directories:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;Touched&lt;span class="w"&gt; &lt;/span&gt;Pages:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20382075&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;77G&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;Elapsed:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;434&lt;/span&gt;.77&lt;span class="w"&gt; &lt;/span&gt;seconds
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When Linux requires RAM, it will incrementally evict the db from memory. To prevent this, we can copy the db to shared memory (/dev/shm) and then use vmtouch to preload the db.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;/dev/shm

$&lt;span class="w"&gt; &lt;/span&gt;vmtouch&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;/dev/shm/*.k2d
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let's run kraken2 with &lt;code&gt;--memory-mapping&lt;/code&gt; option.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--memory-mapping&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="m"&gt;17121245&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3397&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;532&lt;/span&gt;.486s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1929&lt;/span&gt;.2&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;382&lt;/span&gt;.79&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9826671&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;57&lt;/span&gt;.39%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;7294574&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;.61%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt;   &lt;/span&gt;&amp;gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;424&lt;/span&gt;.20s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;.76s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;81&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:54.98&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the classification took only ~10 minutes.&lt;/p&gt;
&lt;h4&gt;Multi threading&lt;/h4&gt;
&lt;p&gt;kraken2 supports multiple threads. I am using a machine with 40 threads.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;--memory-mapping&lt;span class="w"&gt; &lt;/span&gt;--threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="m"&gt;17121245&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3397&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;71&lt;/span&gt;.675s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;14332&lt;/span&gt;.5&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2843&lt;/span&gt;.81&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9826671&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;57&lt;/span&gt;.39%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;7294574&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;.61%&lt;span class="o"&gt;)&lt;/span&gt;
kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;556&lt;/span&gt;.58s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;.85s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;762&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;:16.02&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With 32 threads, the classification took only 1 minute. Beyond 32 threads, the classification time did not decrease significantly.&lt;/p&gt;
&lt;h4&gt;Optimising input files&lt;/h4&gt;
&lt;p&gt;So far we have used gzipped input files. Let's use unzipped input files and run kraken2.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;gunzip&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz
$&lt;span class="w"&gt; &lt;/span&gt;gunzip&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq&lt;span class="w"&gt; &lt;/span&gt;--memory-mapping&lt;span class="w"&gt; &lt;/span&gt;--threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="m"&gt;17121245&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3397&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;34&lt;/span&gt;.809s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;29512&lt;/span&gt;.0&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5855&lt;/span&gt;.68&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;9826671&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;57&lt;/span&gt;.39%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;7294574&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;.61%&lt;span class="o"&gt;)&lt;/span&gt;
kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;565&lt;/span&gt;.03s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;.12s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1530&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;38&lt;/span&gt;.047&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the classification time has come down to 40 seconds.&lt;/p&gt;
&lt;p&gt;Since the input fastq files are paired, interleaving the files also takes time. Lets interleave the files and run kraken2.&lt;/p&gt;
&lt;p&gt;To interleave the files, lets use &lt;code&gt;seqfu&lt;/code&gt; tool.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;conda-forge&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;bioconda&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"seqfu&amp;gt;1.10"&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;seqfu&lt;span class="w"&gt; &lt;/span&gt;interleave&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;-2&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;SRR6915097.fastq

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--memory-mapping&lt;span class="w"&gt; &lt;/span&gt;SRR6915097.fq&lt;span class="w"&gt; &lt;/span&gt;--threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="m"&gt;34242490&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3397&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;.199s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;101714&lt;/span&gt;.1&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10090&lt;/span&gt;.91&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;17983321&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;52&lt;/span&gt;.52%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;16259169&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47&lt;/span&gt;.48%&lt;span class="o"&gt;)&lt;/span&gt;
kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;--memory-mapping&lt;span class="w"&gt; &lt;/span&gt;SRR6915097.fq&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;618&lt;/span&gt;.96s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;.24s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2653&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;24&lt;/span&gt;.013&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the classification time has come down to 24 seconds. &lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In terms of classification speed, we have come a long way from 0.1 Mbp/m to 1200 Mbp/m. In the next post, we will learn how to optimise the creation of custom indices.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:k2"&gt;
&lt;p&gt;&lt;a href="https://ccb.jhu.edu/software/kraken2/"&gt;Kraken2&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fnref:k2" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ksr"&gt;
&lt;p&gt;&lt;a href="https://github.com/DerrickWood/kraken2/blob/master/docs/MANUAL.markdown#system-requirements"&gt;Kraken System Requirements&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fnref:ksr" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:err"&gt;
&lt;p&gt;&lt;a href="ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR103/077/ERR10359977/ERR10359977.fastq.gz"&gt;ERR10359977.fastq.gz&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fnref:err" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:k2p"&gt;
&lt;p&gt;&lt;a href="https://benlangmead.github.io/aws-indexes/k2"&gt;Genomic Index Zone - k2&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fnref:k2p" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:vmt"&gt;
&lt;p&gt;&lt;a href="https://hoytech.com/vmtouch/"&gt;https://hoytech.com/vmtouch/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html#fnref:vmt" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>bioinformatics</category><category>devops</category><category>kraken2</category><category>metagenomics</category><guid>https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html</guid><pubDate>Sun, 28 Jul 2024 05:21:30 GMT</pubDate></item><item><title>Mastering Kraken2 - Part 1 - Initial Runs</title><link>https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Mastering Kraken2&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html"&gt;Part 1 - Initial Runs&lt;/a&gt; (this post)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html"&gt;Part 2 - Classification Performance Optimisation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/07/mastering-kraken2-build-custom-db.html"&gt;Part 3 - Build custom database indices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2024/08/mastering-kraken2-fda-argos-index.html"&gt;Part 4 - Build FDA-ARGOS index&lt;/a&gt; (this post)&lt;/p&gt;
&lt;p&gt;Part 5 - Regular vs Fast Builds (upcoming)&lt;/p&gt;
&lt;p&gt;Part 6 - Benchmarking (upcoming)&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Kraken2&lt;sup id="fnref:Kraken2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fn:Kraken2"&gt;1&lt;/a&gt;&lt;/sup&gt; is widely used for metagenomics taxonomic classification, and it has pre-built indexes for many organisms. In this series, we will learn&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to set up kraken2, download pre-built indices&lt;/li&gt;
&lt;li&gt;Run kraken2 (8GB RAM) at ~0.19 Mbp/m (million base pairs per minute)&lt;/li&gt;
&lt;li&gt;Learn various ways to speed up the classification process&lt;/li&gt;
&lt;li&gt;Run kraken2 (128GB RAM) at ~1200 Mbp/m&lt;/li&gt;
&lt;li&gt;Build custom indices&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Installation&lt;/h4&gt;
&lt;p&gt;We can install kraken2 from source using the &lt;code&gt;install_kraken2.sh&lt;/code&gt; script as per the manual&lt;sup id="fnref:install_kraken2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fn:install_kraken2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/DerrickWood/kraken2
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2
$&lt;span class="w"&gt; &lt;/span&gt;./install_kraken2.sh&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin
&lt;span class="c1"&gt;# ensure kraken2 is in the PATH&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:/usr/local/bin
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you already have conda installed, you can install kraken2 from conda as well.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;bioconda&lt;span class="w"&gt; &lt;/span&gt;kraken2
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you have &lt;code&gt;brew&lt;/code&gt; installed on Linux or Mac(including M1), you can install kraken2 using &lt;code&gt;brew&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;brewsci/bio/kraken2
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Download pre-built indices&lt;/h4&gt;
&lt;p&gt;Building kraken2 indices take a lot of time and resources. For now, let's download and use the pre-built indices. In the final post, we will learn how to build the indices.&lt;/p&gt;
&lt;p&gt;Genomic Index Zone&lt;sup id="fnref:GenomicIndexZone"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fn:GenomicIndexZone"&gt;3&lt;/a&gt;&lt;/sup&gt; provides pre-built indices for kraken2. Let's download the standard database. It contains Refeq archaea, bacteria, viral, plasmid, human1, &amp;amp; UniVec_Core. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://genome-idx.s3.amazonaws.com/kraken/k2_standard_20240605.tar.gz
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;k2_standard
$&lt;span class="w"&gt; &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;-xvf&lt;span class="w"&gt; &lt;/span&gt;k2_standard_20240605.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;k2_standard
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The extracted directory contains three files - &lt;code&gt;hash.k2d&lt;/code&gt;, &lt;code&gt;opts.k2d&lt;/code&gt;, &lt;code&gt;taxo.k2d&lt;/code&gt; which are the kraken2 database files.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;*.k2d
.rw-r--r--&lt;span class="w"&gt;  &lt;/span&gt;83G&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jul&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:34&lt;span class="w"&gt; &lt;/span&gt;hash.k2d
.rw-r--r--&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jul&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:34&lt;span class="w"&gt; &lt;/span&gt;opts.k2d
.rw-r--r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0M&lt;span class="w"&gt; &lt;/span&gt;anand&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Jul&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:34&lt;span class="w"&gt; &lt;/span&gt;taxo.k2d
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Classification&lt;/h4&gt;
&lt;p&gt;To run the taxonomic classification, let's use &lt;code&gt;ERR10359977&lt;/code&gt; human gut meta genome from NCBI SRA.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://ftp.sra.ebi.ac.uk/vol1/fastq/ERR103/077/ERR10359977/ERR10359977.fastq.gz
$&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;ERR10359977.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, the machine I have used has 8GB RAM and an additioinal 8GB swap. Since kraken2 needs entire db(~80GB) in memory, when the process tries to consume more than 16GB memory, the kernel will kill the process. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...Command&lt;span class="w"&gt; &lt;/span&gt;terminated&lt;span class="w"&gt; &lt;/span&gt;by&lt;span class="w"&gt; &lt;/span&gt;signal&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;.02user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;275&lt;/span&gt;.83system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;:17.43elapsed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;%CPU&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To prevent this, let's increase the swap space to 128 GB.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Create an empty swapfile of 128GB&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/swapfile&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1G&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;128&lt;/span&gt;

&lt;span class="c1"&gt;# Turn swap off - It might take several minutes&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;swapoff&lt;span class="w"&gt; &lt;/span&gt;-a

&lt;span class="c1"&gt;# Set the permissions for swapfile&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/swapfile

&lt;span class="c1"&gt;# make it a swap area&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;mkswap&lt;span class="w"&gt; &lt;/span&gt;/swapfile&lt;span class="w"&gt;  &lt;/span&gt;

&lt;span class="c1"&gt;# Turn the swap on&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;swapon&lt;span class="w"&gt; &lt;/span&gt;/swapfile
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can time the classification process using the &lt;code&gt;time&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;ERR10359977.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you have a machine with large RAM, the same scenario can be simulated using &lt;code&gt;systemd-run&lt;/code&gt;. This will limit the memory usage of kraken2 to 6.5GB. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-run&lt;span class="w"&gt; &lt;/span&gt;--scope&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MemoryMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;.5G&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--report&lt;span class="w"&gt; &lt;/span&gt;report.txt&lt;span class="w"&gt; &lt;/span&gt;ERR10359977.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Depending on the CPU performance, this will take around ~40 minutes to complete.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;Loading&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;information...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="m"&gt;95064&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;.35&lt;span class="w"&gt; &lt;/span&gt;Mbp&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;processed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1026&lt;/span&gt;.994s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.6&lt;span class="w"&gt; &lt;/span&gt;Kseq/m,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.84&lt;span class="w"&gt; &lt;/span&gt;Mbp/m&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;94939&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;classified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;99&lt;/span&gt;.87%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;125&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sequences&lt;span class="w"&gt; &lt;/span&gt;unclassified&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.13%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.24user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;658&lt;/span&gt;.68system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;38&lt;/span&gt;:26.78elapsed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;28&lt;/span&gt;%CPU&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we try gut WGS(Whole Genome Sequence) sample like &lt;code&gt;SRR6915097&lt;/code&gt; &lt;sup id="fnref:srr1"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fn:srr1"&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;sup id="fnref:srr2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fn:srr2"&gt;5&lt;/a&gt;&lt;/sup&gt;. which contains ~3.3 Gbp, it will take weeks to complete.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;https://ftp.sra.ebi.ac.uk/vol1/fastq/SRR691/007/SRR6915097/SRR6915097_1.fastq.gz
$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;https://ftp.sra.ebi.ac.uk/vol1/fastq/SRR691/007/SRR6915097/SRR6915097_2.fastq.gz

$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemd-run&lt;span class="w"&gt; &lt;/span&gt;--scope&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MemoryMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6G&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kraken2&lt;span class="w"&gt; &lt;/span&gt;--db&lt;span class="w"&gt; &lt;/span&gt;k2_standard&lt;span class="w"&gt; &lt;/span&gt;--paired&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_1.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;SRR6915097_2.fastq.gz&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I tried running this on 8 GB machine. Even after 10 days, it processed only 10% of the data.&lt;/p&gt;
&lt;p&gt;If we have to process a large number of such samples, it takes months and this is not a practical solution. &lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this post, we ran kraken2 on an 8GB machine and learned that it is not feasible to run kraken2 on large samples.&lt;/p&gt;
&lt;p&gt;In the next post, we will learn how to speed up the classification process and run classification at 1200 Mbp/m.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next&lt;/strong&gt;: &lt;a href="https://avilpage.com/2024/07/mastering-kraken2-performance-optimisation.html"&gt;Part 2 - Performance Optimisation&lt;/a&gt;&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:Kraken2"&gt;
&lt;p&gt;&lt;a href="https://ccb.jhu.edu/software/kraken2/"&gt;Kraken2&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fnref:Kraken2" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:install_kraken2"&gt;
&lt;p&gt;&lt;a href="https://github.com/DerrickWood/kraken2/blob/master/docs/MANUAL.markdown#installation"&gt;Kraken2 - Manual - Install&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fnref:install_kraken2" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:GenomicIndexZone"&gt;
&lt;p&gt;&lt;a href="https://benlangmead.github.io/aws-indexes/k2"&gt;Genomic Index Zone - k2&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fnref:GenomicIndexZone" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:srr1"&gt;
&lt;p&gt;&lt;a href="https://ftp.sra.ebi.ac.uk/vol1/fastq/SRR691/007/SRR6915097/SRR6915097_1.fastq.gz"&gt;SRR6915097_1.fastq.gz&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fnref:srr1" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:srr2"&gt;
&lt;p&gt;&lt;a href="https://ftp.sra.ebi.ac.uk/vol1/fastq/SRR691/007/SRR6915097/SRR6915097_2.fastq.gz"&gt;SRR6915097_1.fastq.gz&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html#fnref:srr2" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>bioinformatics</category><category>kraken2</category><category>metagenomics</category><guid>https://avilpage.com/2024/07/mastering-kraken2-initial-runs.html</guid><pubDate>Sun, 28 Jul 2024 05:14:25 GMT</pubDate></item><item><title>Headlamp - k8s Lens open source alternative</title><link>https://avilpage.com/2024/06/headlamp-k8s-lens-open-source-alternative.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img alt="headlamp - Open source Kubernetes Lens alternator" src="https://avilpage.com/images/headlamp-k8s-lens-open-source-alternative.png"&gt;&lt;/p&gt;
&lt;p&gt;Since Lens is not open source, I tried out monokle, octant, k9s, and headlamp&lt;sup id="fnref:headlamp"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/06/headlamp-k8s-lens-open-source-alternative.html#fn:headlamp"&gt;1&lt;/a&gt;&lt;/sup&gt;. Among them, headlamp UI &amp;amp; features are closest to Lens. &lt;/p&gt;
&lt;h4&gt;Headlamp&lt;/h4&gt;
&lt;p&gt;Headlamp is CNCF sandbox project that provides cross-platform desktop application to manage Kubernetes clusters. It auto-detects clusters and provides cluster wide resource usage by default. &lt;/p&gt;
&lt;p&gt;It can also be installed inside the cluster and can be accessed using a web browser. This is useful when we want to access the cluster from a mobile device.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;helm&lt;span class="w"&gt; &lt;/span&gt;repo&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;headlamp&lt;span class="w"&gt; &lt;/span&gt;https://headlamp-k8s.github.io/headlamp/

$&lt;span class="w"&gt; &lt;/span&gt;helm&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;headlamp&lt;span class="w"&gt; &lt;/span&gt;headlamp/headlamp
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lets port-forward the service &amp;amp; copy the token to access it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;token&lt;span class="w"&gt; &lt;/span&gt;headlamp

&lt;span class="c1"&gt;# we can do this via headlamp UI as well&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;port-forward&lt;span class="w"&gt; &lt;/span&gt;service/headlamp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;:80
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we can access the headlamp UI at &lt;a href="http://"&gt;http://localhost:8080&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="headlamp - Open source Kubernetes Lens alternator" src="https://avilpage.com/images/headlamp-k8s-lens-open-source-alternative2.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;If you are looking for an open source alternative to Lens, headlamp is a good choice. It provides a similar UI &amp;amp; features as Lens, and it is accessible via mobile devices as well. &lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:headlamp"&gt;
&lt;p&gt;&lt;a href="https://headlamp.dev/"&gt;https://headlamp.dev/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/06/headlamp-k8s-lens-open-source-alternative.html#fnref:headlamp" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>kubernetes</category><guid>https://avilpage.com/2024/06/headlamp-k8s-lens-open-source-alternative.html</guid><pubDate>Sun, 23 Jun 2024 20:18:02 GMT</pubDate></item><item><title>macOS - Log &amp; track historical CPU, RAM usage</title><link>https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img alt="macOS - Log CPU &amp;amp; RAM history" src="https://avilpage.com/images/mac-log-cpu-ram-grafana.png"&gt;&lt;/p&gt;
&lt;p&gt;In macOS, we can use inbuilt &lt;code&gt;Activity Monitor&lt;/code&gt; or third party apps like &lt;code&gt;Stats&lt;/code&gt; to check the live CPU/RAM usage. But, we can't track the historical CPU &amp;amp; memory usage. &lt;code&gt;sar&lt;/code&gt;, &lt;code&gt;atop&lt;/code&gt; can track the historical CPU &amp;amp; memory usage. But, they are not available for macOS.&lt;/p&gt;
&lt;h4&gt;Netdata&lt;/h4&gt;
&lt;p&gt;Netdata&lt;sup id="fnref:Netdata"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fn:Netdata"&gt;1&lt;/a&gt;&lt;/sup&gt; is an open source observability tool that can monitor CPU, RAM, network, disk usage. It can also track the historical data. &lt;/p&gt;
&lt;p&gt;Unfortunately, it is not stable on macOS. I tried installing it on multiple macbooks, but it didn't work. I raised an issue&lt;sup id="fnref:netdata_issue"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fn:netdata_issue"&gt;2&lt;/a&gt;&lt;/sup&gt; on their GitHub repository and the team mentioned that macOS is a low priority for them.&lt;/p&gt;
&lt;h4&gt;Glances&lt;/h4&gt;
&lt;p&gt;Glances&lt;sup id="fnref:Glances"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fn:Glances"&gt;3&lt;/a&gt;&lt;/sup&gt; is a cross-platform monitoring tool that can monitor CPU, RAM, network, disk usage. It can also track the historical data.&lt;/p&gt;
&lt;p&gt;We can install it using Brew or pip.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;glances

$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;glances
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once it is installed, we can monitor the resource usage using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;glances
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="macOS - Log CPU &amp;amp; RAM history" src="https://avilpage.com/images/mac-log-cpu-ram-glances.png"&gt;&lt;/p&gt;
&lt;p&gt;Glances can log historical data to a file using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;glances&lt;span class="w"&gt; &lt;/span&gt;--export-csv&lt;span class="w"&gt; &lt;/span&gt;/tmp/glances.csv
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition to that, it can log data to services like influxdb, prometheus, etc.&lt;/p&gt;
&lt;p&gt;Let's install influxdb and export stats to it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;influxdb
$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;services&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;influxdb
$&lt;span class="w"&gt; &lt;/span&gt;influx&lt;span class="w"&gt; &lt;/span&gt;setup

$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;influxdb-client

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;glances.conf
&lt;span class="o"&gt;[&lt;/span&gt;influxdb&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localhost
&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8086&lt;/span&gt;
&lt;span class="nv"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http
&lt;span class="nv"&gt;org&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;avilpage
&lt;span class="nv"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;glances
&lt;span class="nv"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret_token

$&lt;span class="w"&gt; &lt;/span&gt;glances&lt;span class="w"&gt; &lt;/span&gt;--export-influxdb&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;glances.conf
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can view stats in the influxdb from Data Explorer web UI at &lt;a href="http://localhost:8086"&gt;http://localhost:8086&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="macOS - Log CPU &amp;amp; RAM history" src="https://avilpage.com/images/mac-log-cpu-ram-influxdb.png"&gt;&lt;/p&gt;
&lt;p&gt;Glances provides a prebuilt Grafana dashboard&lt;sup id="fnref:grafana_dashboard"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fn:grafana_dashboard"&gt;4&lt;/a&gt;&lt;/sup&gt; that we can import to visualize the stats. &lt;/p&gt;
&lt;p&gt;From Grafana -&amp;gt; Dashboard -&amp;gt; Import, we can import the dashboard using the above URL.&lt;/p&gt;
&lt;p&gt;&lt;img alt="macOS - Log CPU &amp;amp; RAM history" src="https://avilpage.com/images/mac-log-cpu-ram-grafana.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In addition to InfluxDB, Glances can export data to ~20 services. So far, it is the best tool to log, track and view historical CPU, RAM, network and disk usage in macOS. The same method works for Linux and Windows as well.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:Netdata"&gt;
&lt;p&gt;&lt;a href="https://github.com/netdata/netdata"&gt;https://github.com/netdata/netdata&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fnref:Netdata" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:netdata_issue"&gt;
&lt;p&gt;&lt;a href="https://github.com/netdata/netdata/issues/16696"&gt;https://github.com/netdata/netdata/issues/16696&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fnref:netdata_issue" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:Glances"&gt;
&lt;p&gt;&lt;a href="https://github.com/nicolargo/glances"&gt;https://github.com/niolargo/glances&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fnref:Glances" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:grafana_dashboard"&gt;
&lt;p&gt;&lt;a href="https://glances.readthedocs.io/en/latest/gw/influxdb.html#grafana"&gt;https://glances.readthedocs.io/en/latest/gw/influxdb.html#grafana&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html#fnref:grafana_dashboard" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>macbook</category><category>python</category><guid>https://avilpage.com/2024/06/macos-log-track-cpu-ram-usage.html</guid><pubDate>Fri, 31 May 2024 20:18:02 GMT</pubDate></item><item><title>Automating Zscaler Connectivity on macOS</title><link>https://avilpage.com/2024/05/managing-zscaler-connectivity-from-command-line.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Zscaler is a cloud-based security service that provides secure internet access via VPN. Unfortunately, Zscaler does not provide a command-line interface to connect to the VPN. We can't use AppleScript to automate the connectivity as well.&lt;/p&gt;
&lt;h4&gt;Automating Zscaler Connectivity&lt;/h4&gt;
&lt;p&gt;Once Zscaler is installed on macOS, if we search for &lt;code&gt;LaunchAgents&lt;/code&gt; &amp;amp; &lt;code&gt;LaunchDaemons&lt;/code&gt; directories, we can find the Zscaler plist files. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;
/Library/LaunchAgents/com.zscaler.tray.plist


$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;
/Library/LaunchDaemons/com.zscaler.service.plist
/Library/LaunchDaemons/com.zscaler.tunnel.plist
/Library/LaunchDaemons/com.zscaler.UPMServiceController.plist
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To connect to Zscaler, we can load these services.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

/usr/bin/open&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;/Applications/Zscaler/Zscaler.app&lt;span class="w"&gt; &lt;/span&gt;--hide
sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To disconnect from Zscaler, we can unload all of them.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;unload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;unload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To automatically toggle the connectivity, we can create a shell script.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pgrep&lt;span class="w"&gt; &lt;/span&gt;-x&lt;span class="w"&gt; &lt;/span&gt;Zscaler&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Disconnecting from Zscaler"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;unload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;unload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Connecting to Zscaler"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;/usr/bin/open&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;/Applications/Zscaler/Zscaler.app&lt;span class="w"&gt; &lt;/span&gt;--hide
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Raycast is an alternative to default spotlight search on macOS. We can create a script to toggle connectivity to Zscaler.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c1"&gt;# Required parameters:&lt;/span&gt;
&lt;span class="c1"&gt;# @raycast.schemaVersion 1&lt;/span&gt;
&lt;span class="c1"&gt;# @raycast.title toggle zscaler&lt;/span&gt;
&lt;span class="c1"&gt;# @raycast.mode silent&lt;/span&gt;

&lt;span class="c1"&gt;# Optional parameters:&lt;/span&gt;
&lt;span class="c1"&gt;# @raycast.icon ☁️&lt;/span&gt;

&lt;span class="c1"&gt;# Documentation:&lt;/span&gt;
&lt;span class="c1"&gt;# @raycast.author chillaranand&lt;/span&gt;
&lt;span class="c1"&gt;# @raycast.authorURL https://avilpage.com/&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pgrep&lt;span class="w"&gt; &lt;/span&gt;-x&lt;span class="w"&gt; &lt;/span&gt;Zscaler&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Disconnecting from Zscaler"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;unload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;unload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Connecting to Zscaler"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;/usr/bin/open&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;/Applications/Zscaler/Zscaler.app&lt;span class="w"&gt; &lt;/span&gt;--hide
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchAgents&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;/Library/LaunchDaemons&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*zscaler*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-exec&lt;span class="w"&gt; &lt;/span&gt;launchctl&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save this script to a folder. From &lt;code&gt;Raycast Settings&lt;/code&gt; -&amp;gt; &lt;code&gt;Extensions&lt;/code&gt; -&amp;gt; &lt;code&gt;Add Script Directory&lt;/code&gt;, we can select this folder, and the script will be available in Raycast. &lt;/p&gt;
&lt;p&gt;&lt;img alt="raycast-connect-toggle" src="https://avilpage.com/images/automate-zscaler-connect2.png"&gt;&lt;/p&gt;
&lt;p&gt;We can assign a shortcut key to the script for quick access.&lt;/p&gt;
&lt;p&gt;&lt;img alt="raycast-connect-toggle" src="https://avilpage.com/images/automate-zscaler-connect.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Even though Zscaler does not provide a command-line interface, we can automate the connectivity using the above scripts.&lt;/p&gt;</description><category>automation</category><category>macbook</category><guid>https://avilpage.com/2024/05/managing-zscaler-connectivity-from-command-line.html</guid><pubDate>Tue, 14 May 2024 02:19:53 GMT</pubDate></item><item><title>Screen Time Alerts from Activity Watch</title><link>https://avilpage.com/2024/05/screen-time-alerts-from-activity-watch.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/41A0r2H-EXs" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Activity Watch&lt;sup id="fnref:activity_watch"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/05/screen-time-alerts-from-activity-watch.html#fn:activity_watch"&gt;1&lt;/a&gt;&lt;/sup&gt; is a cross-platform open-source time-tracking tool that helps us to track time spent on applications and websites.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Activity Watch" src="https://avilpage.com/images/activity-watch-alerts.png"&gt;&lt;/p&gt;
&lt;p&gt;At the moment, Activity Watch doesn't have any feature to show screen time alerts. In this post, we will see how to show screen time alerts using Activity Watch.&lt;/p&gt;
&lt;h4&gt;Python Script&lt;/h4&gt;
&lt;p&gt;Activity Watch provides an API to interact with the Activity Watch server. We can use the API to get the screen time data and show alerts.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;datetime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;requests&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get_nonafk_events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeperiods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Content-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"charset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"utf-8"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""afk_events = query_bucket(find_bucket('aw-watcher-afk_'));&lt;/span&gt;
&lt;span class="s2"&gt;window_events = query_bucket(find_bucket('aw-watcher-window_'));&lt;/span&gt;
&lt;span class="s2"&gt;window_events = filter_period_intersect(window_events, filter_keyvals(afk_events, 'status', ['not-afk']));&lt;/span&gt;
&lt;span class="s2"&gt;RETURN = merge_events_by_keys(window_events, ['app', 'title']);"""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"timeperiods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;timeperiods&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;"http://localhost:5600/api/0/query/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;"utf-8"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;timeperiods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_nonafk_events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeperiods&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;total_time_secs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;total_time_mins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_time_secs&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Total time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_time_mins&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;divmod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_time_mins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Screen Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; hours &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; minutes"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# show mac notification&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"osascript -e 'display notification &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; hours &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; minutes&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; with title &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Screen TIme&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This script&lt;sup id="fnref:github"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/05/screen-time-alerts-from-activity-watch.html#fn:github"&gt;2&lt;/a&gt;&lt;/sup&gt; will show the screen time alerts using the Activity Watch API. We can run this script using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;screen_time_alerts.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="Screen Time Alerts" src="https://avilpage.com/images/activity-watch-alerts2.png"&gt;&lt;/p&gt;
&lt;p&gt;We can set up a cron job to run this script every hour to show screen time alerts.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;crontab&lt;span class="w"&gt; &lt;/span&gt;-e
&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;screen_time_alerts.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also modify the script to show alerts only when the screen time exceeds a certain limit.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Since Actvity Watch is open-source and provides an API, we can extend its functionality to show screen time alerts. We can also use the API to create custom reports and dashboards.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:activity_watch"&gt;
&lt;p&gt;&lt;a href="https://activitywatch.net/"&gt;Activity Watch&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/05/screen-time-alerts-from-activity-watch.html#fnref:activity_watch" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:github"&gt;
&lt;p&gt;&lt;a href="https://github.com/ChillarAnand/avilpage.com/blob/master/scripts/activity_watch_alerts.py"&gt;Screen Time Alerts Script&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/05/screen-time-alerts-from-activity-watch.html#fnref:github" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>productivity</category><category>python</category><guid>https://avilpage.com/2024/05/screen-time-alerts-from-activity-watch.html</guid><pubDate>Wed, 01 May 2024 01:29:27 GMT</pubDate></item><item><title>Setup FTP server on Mac OS X</title><link>https://avilpage.com/2024/04/how-to-setup-ftp-server-on-mac-os.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/WmmB-6MXRYc" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;On Linux &amp;amp; Mac OS X, Python comes pre-installed. On Windows, we can install it from Windows store or from &lt;a href="https://python.org"&gt;https://python.org&lt;/a&gt; website.&lt;/p&gt;
&lt;p&gt;We can verify the Python version using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;--version
Python&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.11.6
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use the &lt;code&gt;pyftpdlib&lt;/code&gt; library to create an FTP server. We can install the library using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;pyftpdlib
&lt;span class="o"&gt;[&lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;:28:21&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;concurrency&lt;span class="w"&gt; &lt;/span&gt;model:&lt;span class="w"&gt; &lt;/span&gt;async
&lt;span class="o"&gt;[&lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;:28:21&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;masquerade&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;NAT&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;address:&lt;span class="w"&gt; &lt;/span&gt;None
&lt;span class="o"&gt;[&lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;:28:21&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;passive&lt;span class="w"&gt; &lt;/span&gt;ports:&lt;span class="w"&gt; &lt;/span&gt;None
&lt;span class="o"&gt;[&lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;:28:21&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;starting&lt;span class="w"&gt; &lt;/span&gt;FTP&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;:::2121,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;99951&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we can start the FTP server using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pyftpdlib
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It will start the FTP server on port 2121. We can connect to the FTP server using the below command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ftp&lt;span class="w"&gt; &lt;/span&gt;localhost&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2121&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>ftp</category><category>macbook</category><category>python</category><guid>https://avilpage.com/2024/04/how-to-setup-ftp-server-on-mac-os.html</guid><pubDate>Tue, 30 Apr 2024 18:04:14 GMT</pubDate></item><item><title>Timestamp to Relative Time - Kibana Scripted fields</title><link>https://avilpage.com/2024/04/timestamp-to-relative-time-kibana-scripted-fields.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When browsing logs in Kibana, there will be a timestamp stamp field on the left for all the docs. It is difficult to read &amp;amp; comprehend the timestamp in the logs. It would be better if we can convert the timestamp to a human-readable relative time like &lt;code&gt;5 minutes ago&lt;/code&gt;, &lt;code&gt;1 hour ago&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h4&gt;Kibana Scripted Fields&lt;/h4&gt;
&lt;p&gt;Kibana provides a feature called scripted fields to create new fields in the index pattern. We can use this feature to convert the timestamp to a relative time.&lt;/p&gt;
&lt;p&gt;&lt;img alt="kibana-relative-time" src="https://avilpage.com/images/kibana-relative-time1.png"&gt;&lt;/p&gt;
&lt;p&gt;Go to &lt;code&gt;Stack Management&lt;/code&gt; -&amp;gt; &lt;code&gt;Index Patterns&lt;/code&gt; -&amp;gt; &lt;code&gt;Create index pattern&lt;/code&gt; -&amp;gt; Select the index pattern -&amp;gt; &lt;code&gt;Scripted fields&lt;/code&gt;, click on &lt;code&gt;Add scripted field&lt;/code&gt;, add the below script.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;'@timestamp'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toInstant&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;toEpochMilli&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7200000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;" hours ago"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;" hour ago"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;" minutes ago"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;" minute ago"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;" seconds ago"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the field is saved, we can go back to &lt;code&gt;Discover&lt;/code&gt; and see the new field in the logs. We can toggle the visibility of the &lt;code&gt;Relative Time&lt;/code&gt; field to see the relative time.&lt;/p&gt;
&lt;p&gt;&lt;img alt="kibana-relative-time" src="https://avilpage.com/images/kibana-relative-time2.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Instead of looking at the timestamp and calculating the relative time in our head, we can use relative time in Kibana . This will make it easier to read &amp;amp; comprehend the logs.&lt;/p&gt;</description><category>devops</category><category>kibana</category><category>monitoring</category><guid>https://avilpage.com/2024/04/timestamp-to-relative-time-kibana-scripted-fields.html</guid><pubDate>Wed, 10 Apr 2024 08:45:33 GMT</pubDate></item><item><title>The Strange Case of Dr. Linux and Mr. Mac</title><link>https://avilpage.com/2024/03/the-strange-case-of-mac-and-linux.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Few days back, some of the tests started failing on CI server. When I tried to run the tests locally, they were passing.&lt;/p&gt;
&lt;p&gt;After debugging for a while, I found that the tests were failing because of the case sensitivity of the file system. One of the developer was using Linux and had committed 2 files with the same name but different case(&lt;code&gt;config.json&lt;/code&gt;, &lt;code&gt;Config.json&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Linux file system is case-sensitive. So these 2 files will be shown as 2 different files.&lt;/p&gt;
&lt;p&gt;&lt;img alt="linux-file-system" src="https://avilpage.com/images/linux-git-case-sensitive.png"&gt;&lt;/p&gt;
&lt;p&gt;But Mac/Windows file system is case-insensitive. Out of these 2 files, only one file will be shown.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mac-file-system" src="https://avilpage.com/images/mac-git-case-insensitive.png"&gt;&lt;/p&gt;
&lt;p&gt;Due to this, the tests were failing on Linux but passing on Mac. Once the case of the file was corrected, the tests started passing on both the systems.&lt;/p&gt;
&lt;p&gt;I have been using Mac for a long time and never faced this issue. Even though Mac's APFS is case-insensitive, we can create a case-sensitive volume using Disk Utility. &lt;/p&gt;
&lt;p&gt;&lt;img alt="case-sensitive-volume" src="https://avilpage.com/images/mac-case-sensitive-volume.png"&gt;&lt;/p&gt;
&lt;p&gt;We have to be aware of these differences when working on a project with developers using different OS.&lt;/p&gt;</description><category>git</category><category>linux</category><category>macbook</category><guid>https://avilpage.com/2024/03/the-strange-case-of-mac-and-linux.html</guid><pubDate>Sat, 30 Mar 2024 04:23:53 GMT</pubDate></item><item><title>Archiving Option Chain Data</title><link>https://avilpage.com/2024/02/historical-option-chain-india.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;BSE &amp;amp; NSE are the prominent exchanges in India, and they provide option chain data for the stocks &amp;amp; indices listed in their exchange.&lt;/p&gt;
&lt;p&gt;The option chain data is available for the current date. But it is not available for the past dates. This is a problem for traders who want to analyze the historical option chain data.&lt;/p&gt;
&lt;h4&gt;ArchiveBox&lt;/h4&gt;
&lt;p&gt;ArchiveBox&lt;sup id="fnref:archivebox"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/02/historical-option-chain-india.html#fn:archivebox"&gt;1&lt;/a&gt;&lt;/sup&gt; is a tool to archive web pages. It can be used to archive the option chain data for the stocks &amp;amp; indices.&lt;/p&gt;
&lt;p&gt;Let's install ArchiveBox.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;archivebox
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;option_chain
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option_chain
$&lt;span class="w"&gt; &lt;/span&gt;archivebox&lt;span class="w"&gt; &lt;/span&gt;init
$&lt;span class="w"&gt; &lt;/span&gt;archivebox&lt;span class="w"&gt; &lt;/span&gt;setup
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can start the server(defaults to https://localhost:8000) and add URLs manually to archive them.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;archivebox&lt;span class="w"&gt; &lt;/span&gt;server
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="historical-option-chain" src="https://avilpage.com/images/historical-option-chain.png"&gt;&lt;/p&gt;
&lt;p&gt;There are 180+ stocks in FNO segment &amp;amp; 6 indices with weekly expiry. We can write a simple Python script to generate all combinations of URLs for the option chain data and archive them using ArchiveBox.&lt;/p&gt;
&lt;p&gt;Once URLs is generated, we can use the following command to archive them.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;archivebox&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;--input-file&lt;span class="w"&gt; &lt;/span&gt;urls.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These URLs will be archived and stored in the &lt;code&gt;archive&lt;/code&gt; directory. Since we want to archive the data regularly, we can use a schedule to archive daily.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;archivebox&lt;span class="w"&gt; &lt;/span&gt;schedule&lt;span class="w"&gt; &lt;/span&gt;--every&lt;span class="o"&gt;=&lt;/span&gt;day&lt;span class="w"&gt; &lt;/span&gt;--depth&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{{url}}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will archive the option chain data for the stocks &amp;amp; indices on a daily basis.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Browsing the archived data of a single url is a bit difficult. Wayback machine provides a better interface to browse the archived data. I have raised an issue&lt;sup id="fnref:issue"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2024/02/historical-option-chain-india.html#fn:issue"&gt;2&lt;/a&gt;&lt;/sup&gt; regarding the same in the ArchiveBox repository. Once the UI issue is resolved, this will serve as the best tool to browse the historical option chain data.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:archivebox"&gt;
&lt;p&gt;&lt;a href="https://github.com/ArchiveBox/ArchiveBox"&gt;ArchiveBox&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/02/historical-option-chain-india.html#fnref:archivebox" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:issue"&gt;
&lt;p&gt;&lt;a href="https://github.com/ArchiveBox/ArchiveBox/issues/1377"&gt;ArchiveBox Issue&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2024/02/historical-option-chain-india.html#fnref:issue" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>stock-market</category><category>trading</category><guid>https://avilpage.com/2024/02/historical-option-chain-india.html</guid><pubDate>Thu, 29 Feb 2024 08:44:52 GMT</pubDate></item><item><title>Cross Platform File Explorer in 50 lines of code</title><link>https://avilpage.com/2024/01/cross-platform-file-explorer-in-50-lines-of-code.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;In an earlier post, I wrote about why I need a &lt;a href="https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html"&gt;"line count" column in file explorer&lt;/a&gt; and how I wrote a Lua script to see it in xplr file manager.&lt;/p&gt;
&lt;p&gt;xplr has only terminal interface. It is hard for non-developers to use it. I wanted a small team to use this feature so that it will save several hours of their time. So I decided to write a cross-platform GUI app.&lt;/p&gt;
&lt;h4&gt;GUI app&lt;/h4&gt;
&lt;p&gt;Since I am familiar with PySimpleGUI, I decided to write a simple file explorer using it. &lt;/p&gt;
&lt;p&gt;&lt;img alt="Cross Platform File Explorer" src="https://avilpage.com/images/lc_file_explorer.png"&gt;&lt;/p&gt;
&lt;p&gt;As seen in the above screenshot, the file explorer has a "Line Count" column. It is a simple Python script with ~50 lines of code. &lt;/p&gt;
&lt;p&gt;The project is open source and source code is available at &lt;a href="https://github.com/avilpage/lcfileexplorer"&gt;github.com/AvilPage/LCFileExplorer&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Cross Platform&lt;/h4&gt;
&lt;p&gt;A new user can't directly run this Python script on his machine unless Python is already installed. Even if Python is installed, he has to install the required packages and run it. This requires technical expertise.&lt;/p&gt;
&lt;p&gt;To make it easy for non-tech users to run this program, I decided to use &lt;a href="https://www.pyinstaller.org/"&gt;PyInstaller&lt;/a&gt; to create a single executable file for each platform.&lt;/p&gt;
&lt;p&gt;I created a GitHub action to build the executable files for Windows, Linux, and macOS. The action is triggered on every push to the master branch. This will generate &lt;code&gt;.exe&lt;/code&gt; file for Windows, &lt;code&gt;.AppImage&lt;/code&gt; file for Linux, and &lt;code&gt;.dmg&lt;/code&gt; file for macOS. The executable files are uploaded to the artifacts.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;It is easy to create a cross-platform GUI app using Python and PySimpleGUI. It is also easy to distribute the apps built with Python using pyinstaller.&lt;/p&gt;</description><category>automation</category><category>python</category><guid>https://avilpage.com/2024/01/cross-platform-file-explorer-in-50-lines-of-code.html</guid><pubDate>Sat, 27 Jan 2024 12:29:05 GMT</pubDate></item><item><title>Running tests in parallel with pytest &amp; xdist</title><link>https://avilpage.com/2023/12/coverage-reports-with-pytest-xdist.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When tests are taking too long to run, an easy way to speed them up is to run them in parallel.&lt;/p&gt;
&lt;p&gt;When using &lt;code&gt;pytest&lt;/code&gt; as test runner, &lt;code&gt;pytest-xdist&lt;/code&gt; &amp;amp; &lt;code&gt;pytest-parallel&lt;/code&gt; plugins makes it easy to run tests concurrently or in parallel.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pytest-parallel&lt;/code&gt; works better if tests are independent of each other. If tests are dependent on each other, &lt;code&gt;pytest-xdist&lt;/code&gt; is a better choice.&lt;/p&gt;
&lt;p&gt;If there are parameterised tests, pytest-xdist will fail as the order of the tests is not guaranteed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pytest&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;auto&lt;span class="w"&gt; &lt;/span&gt;tests/

Different&lt;span class="w"&gt; &lt;/span&gt;tests&lt;span class="w"&gt; &lt;/span&gt;were&lt;span class="w"&gt; &lt;/span&gt;collected&lt;span class="w"&gt; &lt;/span&gt;between&lt;span class="w"&gt; &lt;/span&gt;gw0&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;gw1.&lt;span class="w"&gt; &lt;/span&gt;The&lt;span class="w"&gt; &lt;/span&gt;difference&lt;span class="w"&gt; &lt;/span&gt;is:&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To fix this, we have to make sure that the parameterised tests are executed in the same order on all workers. It can be achieved by sorting the parameterised tests by their name.&lt;/p&gt;
&lt;p&gt;Alternatively, we can use &lt;code&gt;pytest-randomly&lt;/code&gt; plugin to order the tests.&lt;/p&gt;</description><category>python</category><category>testing</category><guid>https://avilpage.com/2023/12/coverage-reports-with-pytest-xdist.html</guid><pubDate>Sat, 30 Dec 2023 14:46:31 GMT</pubDate></item><item><title>Remap F4 to Raycast, Alfred (cmd + space)</title><link>https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;img src="https://avilpage.com/images/map-f4-raycast-alfred.png"&gt;&lt;/p&gt;
&lt;p&gt;On Mac keyboard, there is &lt;code&gt;F4&lt;/code&gt; key which opens Spotlight&lt;sup id="fnref:spotlight"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fn:spotlight"&gt;1&lt;/a&gt;&lt;/sup&gt; by default. I use Raycast&lt;sup id="fnref:raycast"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fn:raycast"&gt;2&lt;/a&gt;&lt;/sup&gt; a lot instead of Spotlight and wanted to remap &lt;code&gt;F4&lt;/code&gt; to Raycast. &lt;/p&gt;
&lt;p&gt;There is an app called Karabiner-Elements&lt;sup id="fnref:karabiner-elements"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fn:karabiner-elements"&gt;3&lt;/a&gt;&lt;/sup&gt; which can be used to remap keys. After the app is installed, we can use this rule&lt;sup id="fnref:f4"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fn:f4"&gt;4&lt;/a&gt;&lt;/sup&gt; called &lt;code&gt;Map F4 to cmd+space&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;You can import the rule from the above URL directly. Once the rule is imported &amp;amp; enabled, &lt;code&gt;F4&lt;/code&gt; will be remapped to &lt;code&gt;cmd + space&lt;/code&gt; as shown in the video below.&lt;/p&gt;
&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/RX35_wKyQks" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:spotlight"&gt;
&lt;p&gt;&lt;a href="https://support.apple.com/en-in/guide/mac-help/mchlp1008/mac"&gt;https://support.apple.com/en-in/guide/mac-help/mchlp1008/mac&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fnref:spotlight" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:raycast"&gt;
&lt;p&gt;&lt;a href="https://raycast.com/"&gt;https://raycast.com/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fnref:raycast" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:karabiner-elements"&gt;
&lt;p&gt;&lt;a href="https://karabiner-elements.pqrs.org/"&gt;https://karabiner-elements.pqrs.org/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fnref:karabiner-elements" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:f4"&gt;
&lt;p&gt;&lt;a href="https://ke-complex-modifications.pqrs.org/#f4_to_cmd_space"&gt;https://ke-complex-modifications.pqrs.org/#f4_to_cmd_space&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html#fnref:f4" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>macbook</category><category>productivity</category><guid>https://avilpage.com/2023/11/remap-f4-to-raycast-alfred-cmd-%2B-space.html</guid><pubDate>Thu, 30 Nov 2023 18:03:16 GMT</pubDate></item><item><title>Add "Line Count" Column in File Manager</title><link>https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;While monitoring an ETL pipeline, I browse a lot of files and often need to know how many lines are there in a file. For that, I can switch to that directory from terminal and run &lt;code&gt;wc -l&lt;/code&gt; for that.&lt;/p&gt;
&lt;p&gt;To avoid the hassle of switching to the directory and running a command in the terminal, I wrote a simple lua script to show line count column in xplr&lt;sup id="fnref:xplr"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html#fn:xplr"&gt;1&lt;/a&gt;&lt;/sup&gt; file manager.&lt;/p&gt;
&lt;h4&gt;Failed Attempts&lt;/h4&gt;
&lt;p&gt;Initially I set out to write a Finder&lt;sup id="fnref:finder"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html#fn:finder"&gt;2&lt;/a&gt;&lt;/sup&gt; plugin to show the line count column. But I couldn't find a way to get the line count of a file in Finder plugin. I have explored other GUI file managers but none of them have a way to show custom columns with line count.&lt;/p&gt;
&lt;p&gt;Finally, I stumbled upon xplr a TUI file manager, and it was a breeze to write a lua script to show the line count column.&lt;/p&gt;
&lt;h4&gt;xplr - line count&lt;/h4&gt;
&lt;p&gt;xplr can be installed via &lt;code&gt;brew&lt;/code&gt;. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;xplr

$&lt;span class="w"&gt; &lt;/span&gt;xplr&lt;span class="w"&gt; &lt;/span&gt;--version
xplr&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.21.3
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;xplr reads the default configuration from &lt;code&gt;~/.config/xplr/init.lua&lt;/code&gt;. The following configuration shows the line count column in xplr.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'0.21.3'&lt;/span&gt;

&lt;span class="nv"&gt;xplr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fmt_simple_column&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;relative_path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;suffix&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;

&lt;span class="nv"&gt;xplr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;row_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;is_file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"---"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;io.open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;absolute_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;row_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;row_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;row_count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;row_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;


&lt;span class="nv"&gt;xplr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;general&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;cols&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"  path"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"line_count"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;xplr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;general&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;cols&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom.fmt_simple_column"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom.row_count"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;xplr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;general&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;col_widths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Percentage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Percentage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will show a row count on launch.&lt;/p&gt;
&lt;p&gt;&lt;img alt="xplr - line count" src="https://avilpage.com/images/xplr-line-count-column.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;xplr is a very powerful file manager, and it is very easy to write lua scripts to create custom columns. I couldn't find a way to sort items based on the custom column. Need to explore more on that.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:xplr"&gt;
&lt;p&gt;&lt;a href="https://github.com/sayanarijit/xplr"&gt;https://github.com/sayanarijit/xplr&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html#fnref:xplr" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:finder"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Finder_(software)"&gt;https://en.wikipedia.org/wiki/Finder_(software)&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html#fnref:finder" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>command-line</category><category>file manager</category><category>lua</category><guid>https://avilpage.com/2023/11/add-column-for-row-count-in-file-manager.html</guid><pubDate>Mon, 06 Nov 2023 20:43:13 GMT</pubDate></item><item><title>Guide to setting up GeoDjango on Mac M1</title><link>https://avilpage.com/2023/10/guide-to-setting-up-geodjango-on-mac-m1.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;There are a lot of guides on setting up GeoDjango and PostGIS. But most of them are outdated and doesn't work on Mac M1. In this article, let us look at how to set up GeoDjango on Mac M1/M2.&lt;/p&gt;
&lt;p&gt;Ensure you have already installed Postgres on your Mac. &lt;/p&gt;
&lt;h4&gt;Install GeoDjango&lt;/h4&gt;
&lt;p&gt;The default GDAL version available on brew fails to install on Mac M1.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;brew&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gdal&lt;/span&gt;
&lt;span class="o"&gt;==&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cmake&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;--build build&lt;/span&gt;
&lt;span class="k"&gt;Last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;chillaranand&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Library&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Logs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Homebrew&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gdal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;02.&lt;/span&gt;&lt;span class="nl"&gt;cmake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;javac&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Compiling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gdal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20231029&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31808&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;wl9085&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gdal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.7.2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;swig&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;javac&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bootstrap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conjunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;javac&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;longer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;supported&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;later&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;javac&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;longer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;supported&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;later&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;BUILD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FAILED&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gdal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20231029&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31808&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;wl9085&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gdal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.7.2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;swig&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;xml&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Compile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;see&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compiler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;time&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;span class="n"&gt;gmake&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;***&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;swig/java/CMakeFiles/java_binding.dir/build.make:108: swig/java/gdal.jar&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;gmake&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Leaving&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/private/tmp/gdal-20231029-31808-1wl9085/gdal-3.7.2/build'&lt;/span&gt;
&lt;span class="n"&gt;gmake&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;***&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CMakeFiles/Makefile2:9108: swig/java/CMakeFiles/java_binding.dir/all&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;gmake&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Leaving&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/private/tmp/gdal-20231029-31808-1wl9085/gdal-3.7.2/build'&lt;/span&gt;
&lt;span class="nl"&gt;gmake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;***&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Makefile:139: all&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use conda to install gdal. Create a new environment and install gdal in it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;geodjango&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.9
$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;conda-forge&lt;span class="w"&gt; &lt;/span&gt;gdal
$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;django
$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;psycopg2-binary
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once installed, you can check the version using &lt;code&gt;gdalinfo --version&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Remaining dependencies can be installed via brew.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;postgresql
$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;postgis
$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;libgeoip
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's create a new django project and add spatial backends.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;django-admin&lt;span class="w"&gt; &lt;/span&gt;startproject&lt;span class="w"&gt; &lt;/span&gt;geodjango
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;django.contrib.gis&lt;/code&gt; to &lt;code&gt;INSTALLED_APPS&lt;/code&gt; in &lt;code&gt;settings.py&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'django.contrib.gis'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add the following to &lt;code&gt;DATABASES&lt;/code&gt; in &lt;code&gt;settings.py&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;DATABASES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'default'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'ENGINE'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'django.contrib.gis.db.backends.postgis'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since we used conda to install gdal, we need to set the path to gdal in our django settings. Run &lt;code&gt;locate libgdal.dylib&lt;/code&gt; to find the path to gdal.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;GDAL_LIBRARY_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'/opt/homebrew/anaconda3/envs/geodjango/lib/libgdal.dylib'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Similarly, we need to set &lt;code&gt;GEOS_LIBRARY_PATH&lt;/code&gt; as well.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;GEOS_LIBRARY_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'/opt/homebrew/anaconda3/envs/geodjango/lib/libgeos_c.dylib'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we can create a new app and add PointField or any other spatial fields to our models.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;manage.py&lt;span class="w"&gt; &lt;/span&gt;startapp&lt;span class="w"&gt; &lt;/span&gt;places
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib.gis.db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PointField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we looked at how to set up GeoDjango on Mac M1. We used conda to install gdal and brew to install other dependencies. &lt;/p&gt;</description><category>django</category><category>macbook</category><guid>https://avilpage.com/2023/10/guide-to-setting-up-geodjango-on-mac-m1.html</guid><pubDate>Mon, 30 Oct 2023 03:29:23 GMT</pubDate></item><item><title>Remotely Access Raspberry Pi or Any Device</title><link>https://avilpage.com/2023/09/tailscale-remote-ssh-raspberry-pi.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I recently started using Raspberry Pi and I wanted to access it when I am outside of home as well. After trying out few solutions, I stumbled upon Tailscale&lt;sup id="fnref:tailscale"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/09/tailscale-remote-ssh-raspberry-pi.html#fn:tailscale"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Tailscale is a mesh VPN that makes it easy to connect out devices, wherever they are. It is free for personal use and supports all major platforms like Linux, Windows, Mac, Android, iOS, etc.&lt;/p&gt;
&lt;h4&gt;Installation&lt;/h4&gt;
&lt;p&gt;I installed tailscale on Raspberry Pi using the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://tailscale.com/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Setup&lt;/h4&gt;
&lt;p&gt;Once the installation is done, I run &lt;code&gt;tailscale up&lt;/code&gt; to start the daemon. This opened a browser window and asked me to log in with email address. After I logged in, I can see all the devices in the tailscale dashboard.&lt;/p&gt;
&lt;p&gt;&lt;img alt="tailscale dashboard" src="https://avilpage.com/images/tailscale-pi.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tailscale&lt;/code&gt; has CLI tool as well and status can be viewed with the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;tailscale&lt;span class="w"&gt; &lt;/span&gt;status
&lt;span class="m"&gt;100&lt;/span&gt;.81.13.75&lt;span class="w"&gt;   &lt;/span&gt;m1&lt;span class="w"&gt;                    &lt;/span&gt;avilpage@&lt;span class="w"&gt;  &lt;/span&gt;macOS&lt;span class="w"&gt;   &lt;/span&gt;-
&lt;span class="m"&gt;100&lt;/span&gt;.12.12.92&lt;span class="w"&gt;   &lt;/span&gt;rpi1.tailscale.ts.net&lt;span class="w"&gt; &lt;/span&gt;avilpage@&lt;span class="w"&gt;  &lt;/span&gt;linux&lt;span class="w"&gt;   &lt;/span&gt;offline
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I also set up a cron job to start tailscale daemon on boot.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;crontab&lt;span class="w"&gt; &lt;/span&gt;-e
@reboot&lt;span class="w"&gt; &lt;/span&gt;tailscale&lt;span class="w"&gt; &lt;/span&gt;up
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Access&lt;/h4&gt;
&lt;p&gt;Now I can access the device from anywhere using the tailscale IP address. For example, if the IP address is &lt;code&gt;100.34.2.23&lt;/code&gt;. I can ssh into the device using the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;pi@100.81.12.92
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It also provides DNS names for each device. For example, I can ssh into the device using the following command as well.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;pi@raspberry3.tailscale.net
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Tailscale is a great tool to access devices remotely. It is easy to set up and works well with Raspberry Pi, Mac &amp;amp; Linux as well.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:tailscale"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Tailscale"&gt;https://en.wikipedia.org/wiki/Tailscale&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/09/tailscale-remote-ssh-raspberry-pi.html#fnref:tailscale" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>raspberry_pi</category><category>tailscale</category><guid>https://avilpage.com/2023/09/tailscale-remote-ssh-raspberry-pi.html</guid><pubDate>Mon, 25 Sep 2023 01:49:54 GMT</pubDate></item><item><title>Create Telegram Bot To Post Messages to Group</title><link>https://avilpage.com/2023/09/telegram-bot-for-iot-updates.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Recently I had to create a Telegram bot again to post updates to a group based on IoT events. This post is just a reference for future.&lt;/p&gt;
&lt;h4&gt;Create a Telegram Bot&lt;/h4&gt;
&lt;p&gt;First, create a bot using BotFather in the Telegram app and get the API token. Then, create a group and add the bot to the group. This will give the bot access to the group.&lt;/p&gt;
&lt;h4&gt;Post Messages to the Group&lt;/h4&gt;
&lt;p&gt;Now, we need to fetch the group id. For this, we can use the following curl API call. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; is available by default on Mac and Linux terminals. On Windows, we can use &lt;code&gt;curl&lt;/code&gt; from command prompt.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;https://api.telegram.org/bot&amp;lt;API_TOKEN&amp;gt;/getUpdates

&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;true,
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"result"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"update_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;733724271&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"message_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"from"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1122&lt;/span&gt;,
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"is_bot"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;false,
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ChillarAnand"&lt;/span&gt;,
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"language_code"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"chat"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;-114522,
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DailyPythonTips"&lt;/span&gt;,
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"group"&lt;/span&gt;,
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s2"&gt;"all_members_are_administrators"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1694045795&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@DailyPythonTipsBot hi"&lt;/span&gt;,
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"entities"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;"offset"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;,
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;"length"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;,
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mention"&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will return a JSON response with the group id. It sends empty response if there are no recent conversations. &lt;/p&gt;
&lt;p&gt;In that case, send a dummy message to the bot in the group and try again. It should return the group id in the response.&lt;/p&gt;
&lt;p&gt;We can use this group id to post messages to the group.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;https://api.telegram.org/bot&amp;lt;API_TOKEN&amp;gt;/sendMessage&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chat_id=&amp;lt;GROUP_ID&amp;gt;&amp;amp;text=Hello"&lt;/span&gt;

&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;true,
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"result"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"message_id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;,
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"from"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3349238234&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"is_bot"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;true,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DailyPythonTipsBot"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DailyPythonTipsBot"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"chat"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;-114522,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"title"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DailyPythonTips"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"group"&lt;/span&gt;,
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;"all_members_are_administrators"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1694046381&lt;/span&gt;,
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is the message posted by the bot in the group.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/telegram-bot-group-message.jpeg" alt="Telegram Bot for IoT Updates" width="200" height="400"&gt;
&lt;/p&gt;

&lt;p&gt;Now, we can use this API to post messages to the group from our IoT devices or from any other devices where &lt;code&gt;curl&lt;/code&gt; command is available.&lt;/p&gt;</description><category>automation</category><guid>https://avilpage.com/2023/09/telegram-bot-for-iot-updates.html</guid><pubDate>Mon, 04 Sep 2023 13:14:32 GMT</pubDate></item><item><title>Periodically Launch an App in Background</title><link>https://avilpage.com/2023/08/periodically-launch-app-background.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I recently started using Outlook app on my Mac. If the app is closed, it won't send any notifications. When I accidentally close the app, until I re-open it, I won't get any notifications.&lt;/p&gt;
&lt;p&gt;I want to ensure that it starts periodically so that I don't miss any notifications for meetings.&lt;/p&gt;
&lt;p&gt;After trying out various methods, I ended up using &lt;code&gt;open&lt;/code&gt; command with &lt;code&gt;cron&lt;/code&gt; to launch the app every 15 minutes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;crontab&lt;span class="w"&gt; &lt;/span&gt;-e
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;*/15&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/open&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft Outlook"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will launch the app every 15 minutes. This is inconvenient as it will bring Outlook to foreground every 15 minutes. &lt;/p&gt;
&lt;p&gt;To avoid this, I passed &lt;code&gt;-g&lt;/code&gt; option to run it in background.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;crontab&lt;span class="w"&gt; &lt;/span&gt;-e
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;*/15&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/open&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft Outlook"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This silently launches the app in background without causing any disturbance. Since the app is running the background, it will send notifications for any meetings.&lt;/p&gt;
&lt;p&gt;This will ensure that I don't miss any meetings, even if I close outlook accidentally.&lt;/p&gt;</description><category>automation</category><category>command-line</category><category>macbook</category><guid>https://avilpage.com/2023/08/periodically-launch-app-background.html</guid><pubDate>Wed, 23 Aug 2023 13:33:49 GMT</pubDate></item><item><title>Rearrange CSV columns alphabetically from CLI</title><link>https://avilpage.com/2023/08/rearrange-csv-columns-alphabetically-cli.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;We can use tools like KDiff3 to compare two CSV files. But, it is difficult to identify the diff when the columns are not in the same order.&lt;/p&gt;
&lt;p&gt;For example, look at the below output of 2 simple csv files.&lt;/p&gt;
&lt;p&gt;&lt;img alt="kdiff3-csv-compare" src="https://avilpage.com/images/kdiff3-csv-compare.png"&gt;&lt;/p&gt;
&lt;p&gt;Even though it highlights the diff, it is difficult to identify the diff because the columns are not in the same order. Here is the same diff after rearranging the columns alphabetically.&lt;/p&gt;
&lt;p&gt;&lt;img alt="kdiff3-csv-compare-sorted" src="https://avilpage.com/images/kdiff3-csv-compare-sorted.png"&gt;&lt;/p&gt;
&lt;p&gt;Now, it is easy to identify the diff.&lt;/p&gt;
&lt;h4&gt;Rearrange CSV columns alphabetically&lt;/h4&gt;
&lt;p&gt;We can write a simple python script using Pandas&lt;sup id="fnref:pandas"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/08/rearrange-csv-columns-alphabetically-cli.html#fn:pandas"&gt;1&lt;/a&gt;&lt;/sup&gt; as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#! /usr/bin/env python3&lt;/span&gt;

&lt;span class="sd"&gt;"""&lt;/span&gt;
&lt;span class="sd"&gt;re-arrange columns in alphabetical order&lt;/span&gt;
&lt;span class="sd"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pd&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;colsort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;input_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;output_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;output_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_file&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colsort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use this script as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;rearrange_csv_columns.py&lt;span class="w"&gt; &lt;/span&gt;input.csv&lt;span class="w"&gt; &lt;/span&gt;output.csv
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of writing a script by ourselves, we can use &lt;code&gt;miller&lt;/code&gt;&lt;sup id="fnref:miller"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/08/rearrange-csv-columns-alphabetically-cli.html#fn:miller"&gt;2&lt;/a&gt;&lt;/sup&gt; tool. Miller can perform various operations on CSV files. We can use &lt;code&gt;sort-within-records&lt;/code&gt; to sort the columns.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;mlr&lt;span class="w"&gt; &lt;/span&gt;--csv&lt;span class="w"&gt; &lt;/span&gt;sort-within-records&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;input.csv&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;output.csv
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We can use &lt;code&gt;miller&lt;/code&gt; to sort the columns in a CSV file. This will help us to identify the diff easily when comparing two CSV files.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:pandas"&gt;
&lt;p&gt;&lt;a href="https://pandas.pydata.org/"&gt;https://pandas.pydata.org/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/08/rearrange-csv-columns-alphabetically-cli.html#fnref:pandas" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:miller"&gt;
&lt;p&gt;&lt;a href="https://github.com/johnkerl/miller"&gt;https://github.com/johnkerl/miller&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/08/rearrange-csv-columns-alphabetically-cli.html#fnref:miller" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>command-line</category><category>python</category><guid>https://avilpage.com/2023/08/rearrange-csv-columns-alphabetically-cli.html</guid><pubDate>Fri, 04 Aug 2023 01:49:54 GMT</pubDate></item><item><title>Train LLMs with Custom Dataset on Laptop</title><link>https://avilpage.com/2023/07/train-llm-custom-data-laptop.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem Statement&lt;/h4&gt;
&lt;p&gt;I want to train a Large Language Model(LLM)&lt;sup id="fnref:LLM"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fn:LLM"&gt;1&lt;/a&gt;&lt;/sup&gt; with some private documents and query various details.&lt;/p&gt;
&lt;h4&gt;Journey&lt;/h4&gt;
&lt;p&gt;There are open-source available LLMs like Vicuna, LLaMa, etc which can be trained on custom data. However, training these models on custom data is not a trivial task.&lt;/p&gt;
&lt;p&gt;After trying out various methods, I ended up using privateGPT&lt;sup id="fnref:privateGPT"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fn:privateGPT"&gt;2&lt;/a&gt;&lt;/sup&gt; which is quite easy to train on custom documents. There is no need to format or clean up the data as privateGPT can directly consume documents in many formats like txt, html, epub, pdf, etc.&lt;/p&gt;
&lt;h4&gt;Training&lt;/h4&gt;
&lt;p&gt;First, let's clone the repo, install requirements.txt and download the default model.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/imartinez/privateGPT
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;privateGPT
$&lt;span class="w"&gt; &lt;/span&gt;pip3&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;requirements.txt
$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://gpt4all.io/models/ggml-gpt4all-j-v1.3-groovy.bin

$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;example.env&lt;span class="w"&gt; &lt;/span&gt;.env
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;.env
&lt;span class="nv"&gt;MODEL_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;GPT4All
&lt;span class="nv"&gt;MODEL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ggml-gpt4all-j-v1.3-groovy.bin
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I have sourced all documents and kept them in a folder called &lt;code&gt;docs&lt;/code&gt;. Let's ingest(train) the data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;~/docs/*&lt;span class="w"&gt; &lt;/span&gt;source_documents

$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;ingest.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will take a while depending on the number of documents we have. Once the ingestion is done, we can start querying the model.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;privateGPT.py
Enter&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;query:&lt;span class="w"&gt; &lt;/span&gt;Summarise&lt;span class="w"&gt; &lt;/span&gt;about&lt;span class="w"&gt; &lt;/span&gt;Gaaliveedu
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The default &lt;code&gt;GPT4All-J v1.3-groovy&lt;/code&gt;&lt;sup id="fnref:gpt4all"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fn:gpt4all"&gt;3&lt;/a&gt;&lt;/sup&gt; model doesn't provide good results. We can easily swap it with &lt;code&gt;LlamaCpp&lt;/code&gt;&lt;sup id="fnref:llama.cpp"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fn:llama.cpp"&gt;4&lt;/a&gt;&lt;/sup&gt;. Lets download the model and convert it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://huggingface.co/openlm-research/open_llama_13b

$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/ggerganov/llama.cpp.git
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;llama.cpp
$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;convert.py&lt;span class="w"&gt; &lt;/span&gt;../open_llama_13b
Wrote&lt;span class="w"&gt; &lt;/span&gt;../open_llama_13b/ggml-model-f16.bin
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can now update the &lt;code&gt;.env&lt;/code&gt; file to use the new model and start querying again.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;.env
&lt;span class="nv"&gt;MODEL_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;LlamaCpp
&lt;span class="nv"&gt;MODEL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/ggml-model-f16.bin

$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;privateGPT.py
Enter&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;query:&lt;span class="w"&gt; &lt;/span&gt;Summarise&lt;span class="w"&gt; &lt;/span&gt;about&lt;span class="w"&gt; &lt;/span&gt;Gaaliveedu
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;This makes it easy to build domain-specific LLMs and use them for various tasks. I have used this to build a chatbot for my internal docs and it is working well.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:LLM"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Large_language_model"&gt;https://en.wikipedia.org/wiki/Large_language_model&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fnref:LLM" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:privateGPT"&gt;
&lt;p&gt;&lt;a href="https://github.com/imartinez/privateGPT"&gt;https://github.com/imartinez/privateGPT&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fnref:privateGPT" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:gpt4all"&gt;
&lt;p&gt;&lt;a href="https://github.com/nomic-ai/gpt4all"&gt;https://github.com/nomic-ai/gpt4all&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fnref:gpt4all" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:llama.cpp"&gt;
&lt;p&gt;&lt;a href="https://github.com/ggerganov/llama.cpp"&gt;https://github.com/ggerganov/llama.cpp&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/07/train-llm-custom-data-laptop.html#fnref:llama.cpp" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>artificial-intelligence</category><category>python</category><guid>https://avilpage.com/2023/07/train-llm-custom-data-laptop.html</guid><pubDate>Thu, 06 Jul 2023 23:06:42 GMT</pubDate></item><item><title>Remote Debug Docker Container with PyCharm</title><link>https://avilpage.com/2023/06/pycharm-debug-python-app-in-docker.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem Statement&lt;/h4&gt;
&lt;p&gt;How to debug a Python application running inside a Docker container that is launched by a third-party process using PyCharm?&lt;/p&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Install the &lt;code&gt;pydevd-pycharm&lt;/code&gt; package in the Docker image.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'pydevd-pycharm~=222.4554.11'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Add the following lines to the Python script that you want to debug.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pydevd_pycharm&lt;/span&gt;
&lt;span class="n"&gt;pydevd_pycharm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'host.docker.internal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdoutToServer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stderrToServer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Create a new Python Remote Debug configuration in PyCharm with the following settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="PyCharm Remote Debug Configuration" src="https://avilpage.com/images/pycharm-docker-debug.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Run the Remote Debug configuration in PyCharm.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the Docker container with the following command or let a shell script or another package run the container.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;flask_web
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;flask_web
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;pydevd-pycharm&lt;/code&gt; package is a Python debugger that can be used to debug a Python application running inside a Docker container. The &lt;code&gt;pydevd_pycharm.settrace()&lt;/code&gt; function is used to connect the debugger to the PyCharm IDE. The &lt;code&gt;host.docker.internal&lt;/code&gt; is the hostname of the host machine from inside the Docker container. The &lt;code&gt;port&lt;/code&gt; is the port number that is used to connect to the PyCharm IDE. The &lt;code&gt;stdoutToServer&lt;/code&gt; and &lt;code&gt;stderrToServer&lt;/code&gt; are used to redirect the standard output and standard error to the PyCharm IDE.&lt;/p&gt;
&lt;h4&gt;Gotchas&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;You might face the following error depending on the version of the &lt;code&gt;pydevd-pycharm&lt;/code&gt; package.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;Traceback&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;most&lt;span class="w"&gt; &lt;/span&gt;recent&lt;span class="w"&gt; &lt;/span&gt;call&lt;span class="w"&gt; &lt;/span&gt;last&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/flask/cli.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;218&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;locate_app
&lt;span class="w"&gt;    &lt;/span&gt;__import__&lt;span class="o"&gt;(&lt;/span&gt;module_name&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/app/app.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;module&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;pydevd_pycharm
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/pydevd_pycharm.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;module&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;pydevd&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;settrace
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/pydevd.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;41&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;module&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;_pydevd_bundle&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;pydevd_utils
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/_pydevd_bundle/pydevd_utils.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;24&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;module&amp;gt;
&lt;span class="w"&gt;    &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;_pydevd_asyncio_util.pydevd_asyncio_utils&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;eval_async_expression_in_context
ModuleNotFoundError:&lt;span class="w"&gt; &lt;/span&gt;No&lt;span class="w"&gt; &lt;/span&gt;module&lt;span class="w"&gt; &lt;/span&gt;named&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'_pydevd_asyncio_util'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There seems to be an issue with all 223.*.* versions. The solution is to use the 222.*.* version.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You might face &lt;code&gt;ConnectionRefused&lt;/code&gt; error when running the docker container.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/pydevd.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1758&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;_locked_settrace
&lt;span class="w"&gt;    &lt;/span&gt;debugger.connect&lt;span class="o"&gt;(&lt;/span&gt;host,&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Note: connect can raise error.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/pydevd.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;660&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;connect
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;start_client&lt;span class="o"&gt;(&lt;/span&gt;host,&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/lib/python3.10/site-packages/_pydevd_bundle/pydevd_comm.py"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;463&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;start_client
&lt;span class="w"&gt;    &lt;/span&gt;s.connect&lt;span class="o"&gt;((&lt;/span&gt;host,&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="o"&gt;))&lt;/span&gt;
ConnectionRefusedError:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Errno&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;111&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Connection&lt;span class="w"&gt; &lt;/span&gt;refused
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ensure that you have started the Remote Debug configuration in PyCharm before running the docker container.&lt;/p&gt;</description><category>debugging</category><category>docker</category><category>python</category><guid>https://avilpage.com/2023/06/pycharm-debug-python-app-in-docker.html</guid><pubDate>Sun, 11 Jun 2023 15:36:04 GMT</pubDate></item><item><title>Mastering HammerSpoon - Excel Automation</title><link>https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Recently, I have been using Excel a lot. When opening a new Excel file, I have to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Maximize the window&lt;/li&gt;
&lt;li&gt;Select all columns and fit them to its width&lt;/li&gt;
&lt;li&gt;Apply filters to all columns&lt;/li&gt;
&lt;li&gt;Freeze the first row&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When opening and closing multiple Excel files, this becomes a tedious task. So, I decided to automate this and came across Hammerspoon.&lt;/p&gt;
&lt;h4&gt;HammerSpoon&lt;/h4&gt;
&lt;p&gt;Hammerspoon&lt;sup id="fnref:hammerspoon"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html#fn:hammerspoon"&gt;1&lt;/a&gt;&lt;/sup&gt; is a powerful automation tool for macOS. It allows you to write Lua scripts to automate various tasks and make our keybindings.&lt;/p&gt;
&lt;p&gt;First, let's install Hammerspoon using Homebrew.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;hammerspoon
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can write our automation script in &lt;code&gt;~/.hammerspoon/init.lua&lt;/code&gt; file. Let us see how we can automate the above tasks.&lt;/p&gt;
&lt;h4&gt;Automating Excel&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- excel&lt;/span&gt;
&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;appObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focusedWindow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;win&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;appObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;selectMenuItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"Edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Select all"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;appObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;selectMenuItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"Format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Column"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Autofit Selection"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;appObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;selectMenuItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"Data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Auto-filter"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;applicationWatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;appObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;watcher&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;eventType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;activated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;eventType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;launched&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;appName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft Excel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nf"&gt;excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;appObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This script will watch for application events and when Excel is launched or activated, it will call the &lt;code&gt;excel&lt;/code&gt; function. &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;excel&lt;/code&gt; function will maximize the window, select all columns and fit them to it's width, apply filters to all columns.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Free top row&lt;/code&gt; option is not available in the standard menu. So, I have added it to the quick access toolbar and click it via mouse event.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Hammerspoon is a powerful tool for various automation tasks. In addition to that it can replace a lot of utility apps like CheatSheet, BlueSnooze&lt;sup id="fnref:bluesnooze"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html#fn:bluesnooze"&gt;2&lt;/a&gt;&lt;/sup&gt;, Rectangle, ShiftIT&lt;sup id="fnref:shiftit"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html#fn:shiftit"&gt;3&lt;/a&gt;&lt;/sup&gt;, HotKey etc. I have replaced most of the utility apps with Hammerspoon, and it is working great. I will be writing about it in detail in the upcoming posts.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:hammerspoon"&gt;
&lt;p&gt;&lt;a href="https://github.com/Hammerspoon/hammerspoon"&gt;https://github.com/Hammerspoon/hammerspoon&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html#fnref:hammerspoon" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:bluesnooze"&gt;
&lt;p&gt;&lt;a href="https://github.com/odlp/bluesnooze"&gt;https://github.com/odlp/bluesnooze&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html#fnref:bluesnooze" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:shiftit"&gt;
&lt;p&gt;&lt;a href="https://github.com/fikovnik/ShiftIt"&gt;https://github.com/fikovnik/ShiftIt&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html#fnref:shiftit" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>automation</category><category>lua</category><category>macbook</category><guid>https://avilpage.com/2023/05/excel-automation-with-hammerspoon-on-mac.html</guid><pubDate>Sun, 21 May 2023 12:44:00 GMT</pubDate></item><item><title>Record Resource Usage of Single Process</title><link>https://avilpage.com/2023/04/record-resource-usage-per-process.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;On Linux &amp;amp; Mac, we can use an inbuilt &lt;code&gt;top&lt;/code&gt; command line tool to monitor the resource usage of a single process in real time. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# On Linux, for a given pid&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;top&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1234&lt;/span&gt;

&lt;span class="c1"&gt;# On Mac, for a given pid&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;top&lt;span class="w"&gt; &lt;/span&gt;-pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1234&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this article, we will see how to record and plot resource usage of a single process using &lt;code&gt;top&lt;/code&gt; and a Python package called psrecord&lt;sup id="fnref:psrecord"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/04/record-resource-usage-per-process.html#fn:psrecord"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h4&gt;Record Resource Usage&lt;/h4&gt;
&lt;p&gt;In some cases, we need to record the resource usage of a process to use it later. For example, we can use this data to find out the peak resource usage of a process. For this, we can use &lt;code&gt;top&lt;/code&gt; to log resource usage into a text file. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# On Linux, for a given pid&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;top&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1234&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;top.log

&lt;span class="c1"&gt;# On Mac, for a given pid&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;top&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-pid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32515&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'NR%13==0; fflush(stdout)'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;top.log
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once we have the log file, we can view the raw data or we can plot the resource usage by using tools like &lt;code&gt;gnuplot&lt;/code&gt; or &lt;code&gt;matplotlib&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead of using &lt;code&gt;top&lt;/code&gt; command, we can use &lt;code&gt;psrecord&lt;/code&gt; to record the resource usage of a process. &lt;code&gt;psrecord&lt;/code&gt; is a Python package that can be installed all using &lt;code&gt;pip&lt;/code&gt;. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;psrecord
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once installed, we can use &lt;code&gt;psrecord&lt;/code&gt; to record the resource usage of a process. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# record resource usage of a process with pid 1234&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;psrecord&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1234&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--log&lt;span class="w"&gt; &lt;/span&gt;top.log

&lt;span class="c1"&gt;# start and record resource usage of a process&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;psrecord&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;script.py&lt;span class="w"&gt; &lt;/span&gt;--plot&lt;span class="w"&gt; &lt;/span&gt;graph.png
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can view the raw data in the log file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# view raw data&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;top.log
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;a.txt
&lt;span class="c1"&gt;# Elapsed time   CPU (%)     Real (MB)   Virtual (MB)&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.000&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.000&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.000&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;399461&lt;/span&gt;.438
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.000&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;93&lt;/span&gt;.700&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.000&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;399461&lt;/span&gt;.438
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.000&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;96&lt;/span&gt;.300&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.000&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;399461&lt;/span&gt;.438
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.000&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;91&lt;/span&gt;.900&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;.000&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;399461&lt;/span&gt;.438
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is the generated graph.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/single-proc-resource.png" alt="single-proc-resource"&gt;
&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how to record and plot resource usage of a single process using top(inbuilt tool), psrecord(3rd party package).&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:psrecord"&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/psrecord/"&gt;https://pypi.org/project/psrecord/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/04/record-resource-usage-per-process.html#fnref:psrecord" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>linux</category><category>macbook</category><guid>https://avilpage.com/2023/04/record-resource-usage-per-process.html</guid><pubDate>Fri, 14 Apr 2023 00:48:37 GMT</pubDate></item><item><title>Reducing System Load With ChatGPT</title><link>https://avilpage.com/2023/04/reduce-system-load-with-chatgpt.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem Statement&lt;/h4&gt;
&lt;p&gt;I am using M1 Macbook Air for Python development purposes. Since M1 uses ARM architecture, many Python packages don't have wheels for ARM64/aarch64. confluent-kafka-python is one of them. &lt;/p&gt;
&lt;p&gt;I had to run AMD64 docker container to use confluent-kafka-python. Since it is a cross-architecture container, its CPU usage is too high and performance was too slow.  &lt;/p&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;p&gt;To reduce system load, I decided to build aarch64 wheels for confluent-kafka-python. I looked at open issues on GitHub and asked maintainers how to build aarch64 wheels. There was no response&lt;sup id="fnref:librdkafka"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/04/reduce-system-load-with-chatgpt.html#fn:librdkafka"&gt;1&lt;/a&gt;&lt;/sup&gt; from them.&lt;/p&gt;
&lt;p&gt;As a workaround, I asked ChatGPT&lt;sup id="fnref:chatgpt"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/04/reduce-system-load-with-chatgpt.html#fn:chatgpt"&gt;2&lt;/a&gt;&lt;/sup&gt; on how to build confluent-kafka-python aarch64 wheels in a docker container.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/chatgpt-reduce-system-load.png" alt="chatgpt-reduce-system-load"&gt;
&lt;/p&gt;

&lt;p&gt;This initial suggestion didn't work as &lt;code&gt;confluent-kafka-python&lt;/code&gt; depends on &lt;code&gt;librdkafka&lt;/code&gt; which is a C library. I had to build &lt;code&gt;librdkafka&lt;/code&gt; from source for aarch64 and then build &lt;code&gt;confluent-kafka-python&lt;/code&gt; from source.&lt;/p&gt;
&lt;p&gt;To build &lt;code&gt;librdkafka&lt;/code&gt; from the source, I again asked ChatGPT. After making minor changes to the snippet suggested by ChatGPT, I was able to build &lt;code&gt;librdkafka&lt;/code&gt; from the source for aarch64.&lt;/p&gt;
&lt;p&gt;Here is the final snippet:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;22.04&lt;/span&gt;

&lt;span class="n"&gt;ARG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;noninteractive&lt;/span&gt;

&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;wget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;postgresql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;nano&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;less&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mime&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;openjdk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;jre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;headless&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;libpq&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tzdata&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;

&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;setuptools&lt;/span&gt;

&lt;span class="n"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;confluentinc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;confluent&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="n"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;confluent&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;

&lt;span class="n"&gt;COPY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;
&lt;span class="n"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;aarch64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;

&lt;span class="n"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;confluent&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;By running native containers, I was able to reduce the system load by ~50%. With ChatGPT, it is easy to build/tweak programs in languages &amp;amp; environments that we are not familiar with.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:librdkafka"&gt;
&lt;p&gt;&lt;a href="https://github.com/confluentinc/librdkafka/issues/3546#issuecomment-1340237177"&gt;https://github.com/confluentinc/librdkafka/3546&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/04/reduce-system-load-with-chatgpt.html#fnref:librdkafka" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:chatgpt"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/ChatGPT"&gt;https://en.wikipedia.org/wiki/ChatGPT&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/04/reduce-system-load-with-chatgpt.html#fnref:chatgpt" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>artificial-intelligence</category><category>docker</category><category>macbook</category><category>python</category><guid>https://avilpage.com/2023/04/reduce-system-load-with-chatgpt.html</guid><pubDate>Sat, 01 Apr 2023 02:25:49 GMT</pubDate></item><item><title>Automator Quick Action for KDiff3 in Finder</title><link>https://avilpage.com/2023/03/custom-action-mac-finder.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;The need for quick action&lt;/h4&gt;
&lt;p&gt;kdiff3&lt;sup id="fnref:kdiff3"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/03/custom-action-mac-finder.html#fn:kdiff3"&gt;1&lt;/a&gt;&lt;/sup&gt; is a diff &amp;amp; merge tool that compares multiple files/directories and shows the difference line by line and character by character as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mac-finder-kdiff3.png" alt="mac-finder-kdiff3"&gt;&lt;/p&gt;
&lt;p&gt;In Windows, when we select multiple files/directories and right click on them, it will show the option to compare selected items with kdiff3.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mac-finder-kdiff3-windows.png" alt="mac-finder-kdiff3-windows"&gt;&lt;/p&gt;
&lt;p&gt;However, in Macbook, it doesn't show this option. In this tutorial, let us see how we can create the same quick action in the right-click menu when we right-click on the files/directories.&lt;/p&gt;
&lt;h4&gt;Creating Quick Action&lt;/h4&gt;
&lt;p&gt;Let us open Automator&lt;sup id="fnref:automator"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/03/custom-action-mac-finder.html#fn:automator"&gt;2&lt;/a&gt;&lt;/sup&gt;, create new file and select Quick Action.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mac-finder-quick-action.png" alt="mac-finder-automator"&gt;&lt;/p&gt;
&lt;p&gt;On the left side select &lt;code&gt;Utilities&lt;/code&gt; and then select &lt;code&gt;Run Shell Script&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;For Workflow receives current, select &lt;code&gt;files or folders&lt;/code&gt; and then select &lt;code&gt;in Finder&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mac-finder-quick-action2.png" alt="mac-finder-quick-action"&gt;&lt;/p&gt;
&lt;p&gt;Then select pass input &lt;code&gt;as agruments&lt;/code&gt; and in the script section let us add the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;/path/to/kdiff3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After adding the command, save this Quick Action. &lt;/p&gt;
&lt;p&gt;Now if we relaunch Finder app and then select multiple directories, and right click we can see &lt;code&gt;Compare with KDiff3&lt;/code&gt; in quick actions.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mac-finder-kdiff3-quick-action.png" alt="mac-finder-kdiff3"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Even though we can use the command line to compare the files/directories, it is always good to have a quick action in the right-click menu. &lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:kdiff3"&gt;
&lt;p&gt;&lt;a href="https://kdiff3.sourceforge.io"&gt;https://kdiff3.sourceforge.io&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/03/custom-action-mac-finder.html#fnref:kdiff3" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:automator"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Automator_(macOS)"&gt;https://en.wikipedia.org/wiki/Automator_(macOS)&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/03/custom-action-mac-finder.html#fnref:automator" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>automation</category><category>macbook</category><guid>https://avilpage.com/2023/03/custom-action-mac-finder.html</guid><pubDate>Fri, 10 Mar 2023 02:54:11 GMT</pubDate></item><item><title>Setup Kubernetes Anywhere with Single Command</title><link>https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/Vo0mAsXe-hI" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In an earlier article, we have seen how to set up &lt;a href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html"&gt;Kubernetes on M1 Mac&lt;/a&gt;. That involved spinning up a VM and installing Kubernetes&lt;sup id="fnref:kubernetes"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fn:kubernetes"&gt;1&lt;/a&gt;&lt;/sup&gt; on it. In this article, we will see how to set up Kubernetes directly on Docker so that we can use the same set-up on any operating system.&lt;/p&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;Ensure you have Docker installed on your system. If you are on a Mac or Windows, you can install Docker Desktop&lt;sup id="fnref:docker-desktop"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fn:docker-desktop"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h4&gt;k3s/k3d&lt;/h4&gt;
&lt;p&gt;k3s&lt;sup id="fnref:k3s"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fn:k3s"&gt;3&lt;/a&gt;&lt;/sup&gt; is a lightweight Kubernetes distribution by Rancher. It is a single binary that can be run on any Linux machine. But it doesn't work on Mac or Windows.&lt;/p&gt;
&lt;p&gt;k3d&lt;sup id="fnref:k3d"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fn:k3d"&gt;4&lt;/a&gt;&lt;/sup&gt; is a wrapper around k3s that allows you to run k3s on Docker. It is a great option for running Kubernetes on your local machine.&lt;/p&gt;
&lt;h4&gt;Installation&lt;/h4&gt;
&lt;p&gt;k3d can be installed using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;k3d&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# mac&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;chocolatey&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;k3d&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# windows&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# linux&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once it is installed, we can create a cluster using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;k3d&lt;span class="w"&gt; &lt;/span&gt;cluster&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;demo
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will launch a cluster with a single node. We can also setup a multi-node cluster using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;k3d&lt;span class="w"&gt; &lt;/span&gt;cluster&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;--servers&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--agents&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can verify the cluster is up and running using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;nodes
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also use GUI tools like Lens to manage and navigate the cluster. In the above video we have used Lens to create a Jenkins deployment as well.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how to set up Kubernetes on Docker. This is a great option for running Kubernetes on your local machine. We can also use this to run production setup for small applications.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:kubernetes"&gt;
&lt;p&gt;&lt;a href="https://kubernetes.io/"&gt;https://kubernetes.io/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fnref:kubernetes" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:docker-desktop"&gt;
&lt;p&gt;&lt;a href="https://www.docker.com/products/docker-desktop/"&gt;https://www.docker.com/products/docker-desktop/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fnref:docker-desktop" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:k3s"&gt;
&lt;p&gt;&lt;a href="https://k3s.io/"&gt;https://k3s.io/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fnref:k3s" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:k3d"&gt;
&lt;p&gt;&lt;a href="https://k3d.io/"&gt;https://k3d.io/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html#fnref:k3d" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>docker</category><category>kubernetes</category><guid>https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html</guid><pubDate>Fri, 03 Mar 2023 21:25:27 GMT</pubDate></item><item><title>Using Conda/Mamba with Python Pip on M1 Mac</title><link>https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;From 2020, all Apple MacBooks are powered by Apple Silicone(M1) chips. This chip uses Aarch64 architecture which is different from x86 architecture which was used by Intel chips earlier.&lt;/p&gt;
&lt;p&gt;Python is a cross-platform language. It can run on any platform. However, Python packages are compiled for specific platforms. For example, a package compiled for x86 will not work on  Aarch64 platform. Also, many Python packages are not yet available for ARM64/Aarch64 platform.&lt;/p&gt;
&lt;h4&gt;M1 Mac and Python&lt;/h4&gt;
&lt;p&gt;If we want to run a python package on M1 Mac which doesn't have ARM64 support, we need to use an emulator(or a cross-architecture Docker image). This will significantly slow down the application.&lt;/p&gt;
&lt;p&gt;An alternate solution is to build packages for ARM64 platform. Building binary packages from the source code requires a lot of time and effort. Also, we need to build the package for each Python version.&lt;/p&gt;
&lt;p&gt;Instead of building from source, we can use Conda/Mamba to install Python packages as well as other system packages. Conda/Mamba will automatically install the correct binary for the package.&lt;/p&gt;
&lt;p&gt;For example, python-confluent-kafka&lt;sup id="fnref:confluent-kafka"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html#fn:confluent-kafka"&gt;3&lt;/a&gt;&lt;/sup&gt; package doesn't have Linux aarch64 support. To run it on aarch64 platform, we have to build from source which takes a lot of time. Instead, we can simply install it using Conda/Mamba with a single command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;conda-forge&lt;span class="w"&gt; &lt;/span&gt;python-confluent-kafka
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Similar to pip, Conda can also install all the packages mentioned in a file like &lt;code&gt;requirements.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;conda&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--file&lt;span class="w"&gt; &lt;/span&gt;requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In data science ecosystem, Conda&lt;sup id="fnref:conda"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html#fn:conda"&gt;1&lt;/a&gt;&lt;/sup&gt;/Mamba&lt;sup id="fnref:mamba"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html#fn:mamba"&gt;2&lt;/a&gt;&lt;/sup&gt; are widely used as package managers. In web development ecosystem, they are not as widely used as pip.&lt;/p&gt;
&lt;p&gt;Conda/Mamba is a great cross-platform system package manager, and it doesn't have all the Python packages available on PyPi. However, we can use it along with pip for easy package management on M1 Macbook.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:conda"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Conda_(package_manager)"&gt;https://en.wikipedia.org/wiki/Conda_(package_manager)&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html#fnref:conda" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:mamba"&gt;
&lt;p&gt;&lt;a href="https://github.com/mamba-org/mamba"&gt;https://github.com/mamba-org/mamba&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html#fnref:mamba" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:confluent-kafka"&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/confluent-kafka/"&gt;https://pypi.org/project/confluent-kafka/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html#fnref:confluent-kafka" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>macbook</category><category>python</category><guid>https://avilpage.com/2023/02/using-conda-mamba-instead-of-pip-on-m1-mac.html</guid><pubDate>Mon, 27 Feb 2023 19:31:01 GMT</pubDate></item><item><title>Hot Module Reload In Python With Reloadium</title><link>https://avilpage.com/2023/02/stateful-hot-module-reload-in-python.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Hot module reloading is a feature that allows you to reload a module without restarting the whole application. This is very useful when we are developing/debugging an application, and we want to see the changes instantaneously.&lt;/p&gt;
&lt;h4&gt;Reloadium&lt;/h4&gt;
&lt;p&gt;Reloadium&lt;sup id="fnref:reloadium"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2023/02/stateful-hot-module-reload-in-python.html#fn:reloadium"&gt;1&lt;/a&gt;&lt;/sup&gt; is an advanced hot reloading library for python.&lt;/p&gt;
&lt;p&gt;Instead of writing an article, I thought it would be much easier to show a live demo of Reloadium. In the below video, we can see how reloadium greatly improves developer experience.&lt;/p&gt;
&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/9UO1raFQdo8" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Currently, reloadium can be used as a standalone tool. We can install it from PyPi and run any arbitrary python script with reloadium.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reloadium&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reloadium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;myscript&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, it is available as a plugin for PyCharm as shown in the above video. VS Code support is also in the works.&lt;/p&gt;
&lt;p&gt;Reloadium is capable of profiling too. Without writing a single line of code, we can profile Python code. But that's a topic for another article.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;I have been using Reloadium from a few months, and it has become an essential part of my development workflow. These days I always run all the scripts or apps in debug mode with reloadium directly. &lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:reloadium"&gt;
&lt;p&gt;&lt;a href="https://github.com/reloadware/reloadium"&gt;https://github.com/reloadware/reloadium&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2023/02/stateful-hot-module-reload-in-python.html#fnref:reloadium" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>hot-reload</category><category>python</category><guid>https://avilpage.com/2023/02/stateful-hot-module-reload-in-python.html</guid><pubDate>Thu, 16 Feb 2023 06:28:58 GMT</pubDate></item><item><title>Best Pay After Placement Courses In India</title><link>https://avilpage.com/2023/01/top-pay-after-placement-courses-in-india.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In India, huge number of students are graduating every year. Most of them are not able to get a job right after graduation. In order to get a job in IT industry, students need to have some technical skills.&lt;/p&gt;
&lt;p&gt;There are thousands of institutes in India that are providing paid technical courses. Depending on the course, the fees can be anywhere between 5,000 to 5 lakhs. The percentage of students who are getting a job after doing these courses is extremely low. In addition to that quite a few students are not able to afford fees to join these courses.&lt;/p&gt;
&lt;h4&gt;Pay After Placement Courses&lt;/h4&gt;
&lt;p&gt;To combat this problem, some institutes are providing pay after placement(PAP) courses. In these courses, students will pay the fees only after getting a job with a desired package. This is a win-win situation for both the students and the institutes. This is a far better option than paying the fees upfront and not getting a job. These courses are also called as income share agreement(ISA) courses.&lt;/p&gt;
&lt;p&gt;Here is a list of top pay after placement courses in India for front end developers, back end developers, full stack developers, data scientists, machine learning engineers, and data engineers.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Site-Rank&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Institute&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Fee(Approx INR)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;134,988&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://www.sharpener.tech/"&gt;Sharpener Tech&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;68,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;59,928&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://acciojob.com/"&gt;AccioJob&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;177,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;321,989&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://placewit.com/"&gt;Placewit&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;0 (Upto 10L)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;37,294&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://www.masaischool.com/"&gt;Masai School&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;350,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;1,482,058&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://digikull.com/"&gt;Digikul&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;234,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;1,554,412&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://www.the10xacademy.com/"&gt;10xAcademy&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;295,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;295,708&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://www.functionup.org/"&gt;Function Up&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;295,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;84,513&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;a href="https://www.almabetter.com/"&gt;AlmaBetter&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Not known&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Most of these courses have an entrance test that candidates have to clear before joining the course. However taking these courses is far better than paying the fees upfront and not getting a job. If you are interested in any of these courses, you can apply for the entrance test and join the course.&lt;/p&gt;</description><category>careers</category><category>placement</category><guid>https://avilpage.com/2023/01/top-pay-after-placement-courses-in-india.html</guid><pubDate>Mon, 23 Jan 2023 12:31:14 GMT</pubDate></item><item><title>Pipe tail output into column</title><link>https://avilpage.com/2023/01/pipe-tail-output-into-column.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;code&gt;column&lt;/code&gt; command-line utility formats its input into multiple columns and aligns it nicely. It is useful for formatting output of csv files, or other commands. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;users.csv
id,user,active
&lt;span class="m"&gt;1&lt;/span&gt;,John&lt;span class="w"&gt; &lt;/span&gt;Doe,true
&lt;span class="m"&gt;2&lt;/span&gt;,Will&lt;span class="w"&gt; &lt;/span&gt;Smith,false

$&lt;span class="w"&gt; &lt;/span&gt;column&lt;span class="w"&gt; &lt;/span&gt;-s,&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;users.csv
id&lt;span class="w"&gt;  &lt;/span&gt;user&lt;span class="w"&gt;        &lt;/span&gt;active
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;John&lt;span class="w"&gt; &lt;/span&gt;Doe&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Will&lt;span class="w"&gt; &lt;/span&gt;Smith&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;tail&lt;/code&gt; command-line utility prints the last 10 lines of a file. It can be used with &lt;code&gt;-f&lt;/code&gt; option to follow the file as it grows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;users.csv
id,user,active
&lt;span class="m"&gt;1&lt;/span&gt;,John&lt;span class="w"&gt; &lt;/span&gt;Doe,true
&lt;span class="m"&gt;2&lt;/span&gt;,Will&lt;span class="w"&gt; &lt;/span&gt;Smith,false
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To format the output of &lt;code&gt;tail -f&lt;/code&gt; command, we can't use &lt;code&gt;column&lt;/code&gt; command directly. &lt;code&gt;column&lt;/code&gt; command can't produce output until it receives all the input. It needs all the input beforehand to calculate the column widths. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;users.csv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;column&lt;span class="w"&gt; &lt;/span&gt;-s,&lt;span class="w"&gt; &lt;/span&gt;-t
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, the above command won't work. &lt;/p&gt;
&lt;p&gt;As the goal is to follow the output of the file, we can use &lt;code&gt;watch&lt;/code&gt; command for this. &lt;code&gt;watch&lt;/code&gt; command executes a command periodically, and displays its output. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;watch&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tail -n 20 users.csv | column -s, -t"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will fetch the last 20 lines of the file, pipe it to column command, and display the output. It will repeat the command every 1 second.&lt;/p&gt;
&lt;p&gt;As the file grows beyond 20 lines, the headers will be truncated. To preserve the headers, we can use &lt;code&gt;head&lt;/code&gt; command in addition to &lt;code&gt;tail&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;watch&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(head -n1 &amp;amp;&amp;amp; tail -n20) &amp;lt; users.csv| column -s, -t"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will print the first line of the file, and then the last 20 lines of the file. The output will be piped to &lt;code&gt;column&lt;/code&gt; command, and displayed.&lt;/p&gt;
&lt;p&gt;Here is a screenshot of the output of a demo csv.&lt;/p&gt;
&lt;p&gt;&lt;img alt="pipe tail output to column" src="https://avilpage.com/images/pipe-tail-output-into-column.png"&gt;&lt;/p&gt;
&lt;p&gt;This makes it easy to watch the output of a file as it grows.&lt;/p&gt;</description><category>command-line</category><category>linux</category><guid>https://avilpage.com/2023/01/pipe-tail-output-into-column.html</guid><pubDate>Mon, 02 Jan 2023 00:56:28 GMT</pubDate></item><item><title>Change Kafka Log Directory &amp; Format It</title><link>https://avilpage.com/2022/12/change-kafka-log-dir-format.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Problem Statement&lt;/h4&gt;
&lt;p&gt;On my local Mac, I was using Kafka to pass messages between various applications. Due to some reason, when I tried to start Kafka recently, it was failing to start and here are the relevant error logs.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2022&lt;/span&gt;-12-23&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;:57:06,217&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;WARN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Controller&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;writeNoOpRecord:&lt;span class="w"&gt; &lt;/span&gt;failed&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;unknown&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;exception&lt;span class="w"&gt; &lt;/span&gt;RuntimeException&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;epoch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;139&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5198&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;us.&lt;span class="w"&gt;  &lt;/span&gt;Renouncing&lt;span class="w"&gt; &lt;/span&gt;leadership&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;reverting&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;last&lt;span class="w"&gt; &lt;/span&gt;committed&lt;span class="w"&gt; &lt;/span&gt;offset&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;927938&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;org.apache.kafka.controller.QuorumController&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2022&lt;/span&gt;-12-23&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;:57:06,536&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ERROR&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Controller&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;registerBroker:&lt;span class="w"&gt; &lt;/span&gt;unable&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;processing&lt;span class="w"&gt; &lt;/span&gt;because&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;NotControllerException.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;org.apache.kafka.controller.QuorumController&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2022&lt;/span&gt;-12-23&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:23:35,834&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ERROR&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;RaftManager&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;nodeId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Had&lt;span class="w"&gt; &lt;/span&gt;an&lt;span class="w"&gt; &lt;/span&gt;error&lt;span class="w"&gt; &lt;/span&gt;during&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;cleaning&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;org.apache.kafka.raft.KafkaRaftClient&lt;span class="o"&gt;)&lt;/span&gt;
org.apache.kafka.common.errors.OffsetOutOfRangeException:&lt;span class="w"&gt; &lt;/span&gt;Cannot&lt;span class="w"&gt; &lt;/span&gt;increment&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;offset&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;927939&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;partition&lt;span class="w"&gt; &lt;/span&gt;__cluster_metadata-0&lt;span class="w"&gt; &lt;/span&gt;since&lt;span class="w"&gt; &lt;/span&gt;it&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;larger&lt;span class="w"&gt; &lt;/span&gt;than&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;high&lt;span class="w"&gt; &lt;/span&gt;watermark&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;926507&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2022&lt;/span&gt;-12-23&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:23:36,035&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;WARN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Controller&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;writeNoOpRecord:&lt;span class="w"&gt; &lt;/span&gt;failed&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;unknown&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;exception&lt;span class="w"&gt; &lt;/span&gt;RuntimeException&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;epoch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;294&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;137&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;us.&lt;span class="w"&gt;  &lt;/span&gt;Renouncing&lt;span class="w"&gt; &lt;/span&gt;leadership&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;reverting&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;last&lt;span class="w"&gt; &lt;/span&gt;committed&lt;span class="w"&gt; &lt;/span&gt;offset&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;927938&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;org.apache.kafka.controller.QuorumController&lt;span class="o"&gt;)&lt;/span&gt;
java.lang.RuntimeException:&lt;span class="w"&gt; &lt;/span&gt;Cant&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;-memory&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;epoch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;926507&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;because&lt;span class="w"&gt; &lt;/span&gt;there&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;already&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;epoch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;927938&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2022&lt;/span&gt;-12-23&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:23:36,252&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ERROR&lt;span class="w"&gt; &lt;/span&gt;Exiting&lt;span class="w"&gt; &lt;/span&gt;Kafka&lt;span class="w"&gt; &lt;/span&gt;due&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;fatal&lt;span class="w"&gt; &lt;/span&gt;exception&lt;span class="w"&gt; &lt;/span&gt;during&lt;span class="w"&gt; &lt;/span&gt;startup.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;kafka.Kafka$&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Debugging&lt;/h4&gt;
&lt;p&gt;I tried to figure out the exact root cause. After multiple failed attempts, I decided to change the log directory temporarily and go ahead for now.&lt;/p&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;p&gt;I create a new temporary directory and set the log directory to that.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;/tmp/kafka-logs

&lt;span class="c1"&gt;# inside server.properties&lt;/span&gt;
log.dirs&lt;span class="o"&gt;=&lt;/span&gt;/tmp/kafka-logs
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When I started the Kafka server, it failed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kafka-server-start&lt;span class="w"&gt; &lt;/span&gt;server.properties

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2022&lt;/span&gt;-12-23&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;:30:50,018&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ERROR&lt;span class="w"&gt; &lt;/span&gt;Exiting&lt;span class="w"&gt; &lt;/span&gt;Kafka&lt;span class="w"&gt; &lt;/span&gt;due&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;fatal&lt;span class="w"&gt; &lt;/span&gt;exception&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;kafka.Kafka$&lt;span class="o"&gt;)&lt;/span&gt;
org.apache.kafka.common.KafkaException:&lt;span class="w"&gt; &lt;/span&gt;No&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;meta.properties&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;found&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/tmp/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;have&lt;span class="w"&gt; &lt;/span&gt;you&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kafka-storage.sh&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;format&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;directory?&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I ran the &lt;code&gt;kafka-storage&lt;/code&gt; script to format the directory. First, we need to get the cluster-id. Since we already know the old kafa-logs directory, we can get the cluster-id from there.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/homebrew/var/lib/kraft-combined-logs/meta.properties&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#Thu Oct 20 11:48:12 IST 2022&lt;/span&gt;
cluster.id&lt;span class="o"&gt;=&lt;/span&gt;5MB5lq-XT-6JzQqJeIuhWQ
node.id&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we can format the new directory.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kafka-storage&lt;span class="w"&gt; &lt;/span&gt;format&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;server.properties&lt;span class="w"&gt; &lt;/span&gt;--cluster-id&lt;span class="w"&gt; &lt;/span&gt;5MB5lq-XT-6JzQqJeIuhWQ

Formatting&lt;span class="w"&gt; &lt;/span&gt;/tmp/kafka-logs/&lt;span class="w"&gt; &lt;/span&gt;with&lt;span class="w"&gt; &lt;/span&gt;metadata.version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.3-IV3.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After changing log directory, Kafka has started working.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kafka-start-server&lt;span class="w"&gt; &lt;/span&gt;/path/to/server.properties
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since I have changed log directory all older messages are lost. Since I am doing this on my local machine, it is fine. Need to revisit it to debug further.&lt;/p&gt;</description><category>debugging</category><category>kafka</category><category>message-broker</category><guid>https://avilpage.com/2022/12/change-kafka-log-dir-format.html</guid><pubDate>Sat, 24 Dec 2022 06:49:41 GMT</pubDate></item><item><title>Hands-on RabbitMQ Tutorial</title><link>https://avilpage.com/2022/12/hands-on-rabbitmq-tutorial.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;A short hands-on guide to get started with RabbitMQ for people who are in a hurry.&lt;/p&gt;
&lt;h4&gt;What is RabbitMQ?&lt;/h4&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/rabbitmq-overview.png" alt="RabbitMQ"&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;Image Credit: CloudAMQP&lt;/p&gt;

&lt;p&gt;RabbitMQ&lt;sup id="fnref:wikipedia-rabbitmq"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/12/hands-on-rabbitmq-tutorial.html#fn:wikipedia-rabbitmq"&gt;1&lt;/a&gt;&lt;/sup&gt; is an open-source message broker software that implements the Advanced Message Queuing Protocol (AMQP). With RabbitMQ, producer and consumer applications can communicate asynchronously, and they will be completely decoupled. &lt;/p&gt;
&lt;h4&gt;RabbitMQ Terminology&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;Producer&lt;/b&gt;: A producer is a client that publishes messages to the RabbitMQ broker. Producers write data to exchanges.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consumer&lt;/b&gt;: A consumer is a client that subscribes to queues and processes the messages. Consumers read data from queues.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Queue&lt;/b&gt;: A queue is a buffer that stores messages. A queue is bound to an exchange and receives messages from it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Exchange&lt;/b&gt;: An exchange is a message routing agent that receives messages from producers and routes them to queues.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Binding&lt;/b&gt;: A binding is a link between an exchange and a queue. It is created with a routing key. The producer sends messages to the exchange with a routing key. The exchange routes the message to the queues that are bound with a matching routing key.&lt;/p&gt;
&lt;h4&gt;RabbitMQ Setup&lt;/h4&gt;
&lt;p&gt;We can use the official RabbitMQ docker image to run RabbitMQ locally. We can run the following command to start a RabbitMQ container:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="o"&gt;=&lt;/span&gt;rabbitmq&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15672&lt;/span&gt;:15672&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5672&lt;/span&gt;:5672&lt;span class="w"&gt; &lt;/span&gt;rabbitmq:3-management
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This image has rabbitmq management plugin enabled. We can access the management UI at &lt;a href="http://localhost:15672"&gt;http://localhost:15672&lt;/a&gt;. The default username and password are both &lt;code&gt;guest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It also has &lt;code&gt;rabbitmqadmin&lt;/code&gt; command line tool installed, which can manage RabbitMQ. &lt;/p&gt;
&lt;h4&gt;Passing Messages from UI&lt;/h4&gt;
&lt;p&gt;We can use the management UI to send and receive messages. We can create a new queue and exchange from the &lt;code&gt;Queues&lt;/code&gt; section.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/rabbitmq-queue.png" alt="RabbitMQ Queue"&gt;&lt;/p&gt;
&lt;p&gt;Once a queue is created, we can publish and consume messages from that queue. &lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/rabbitmq-publish.png" alt="RabbitMQ Publish"&gt;&lt;/p&gt;
&lt;h4&gt;Passing Messages from CLI&lt;/h4&gt;
&lt;p&gt;Instead of using web UI, we can use &lt;code&gt;rabbitmqadmin&lt;/code&gt; CLI tool&lt;sup id="fnref:rabbitmq-cli"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/12/hands-on-rabbitmq-tutorial.html#fn:rabbitmq-cli"&gt;2&lt;/a&gt;&lt;/sup&gt; to send and receive messages. Let's create a topic exchange and a queue. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rabbitmq&lt;span class="w"&gt; &lt;/span&gt;rabbitmqadmin&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;declare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;exchange&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;direct&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders
&lt;span class="c1"&gt;# =&amp;gt; exchange declared&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rabbitmq&lt;span class="w"&gt; &lt;/span&gt;rabbitmqadmin&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;declare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;queue&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders
&lt;span class="c1"&gt;# =&amp;gt; queue declared&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's publish a message to the exchange:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rabbitmq&lt;span class="w"&gt; &lt;/span&gt;rabbitmqadmin&lt;span class="w"&gt; &lt;/span&gt;publish&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;routing_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'dummy message'&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Message published&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To receive messages from the queue, we can use the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rabbitmq&lt;span class="w"&gt; &lt;/span&gt;rabbitmqadmin&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src="https://avilpage.com/images/rabbitmq-get-message.png" alt="RabbitMQ CLI"&gt;&lt;/p&gt;
&lt;h4&gt;Passing Messages from REST API&lt;/h4&gt;
&lt;p&gt;We can also use REST API to send and receive messages. Let's create a new exchange and queue:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;guest:guest&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;PUT&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content-type:application/json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"type":"direct"}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://localhost:15672/api/exchanges/%2f/orders
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;guest:guest&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;PUT&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content-type:application/json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"type":"topic", "durable": true}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://localhost:15672/api/queues/%2f/orders
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can publish a message to the exchange:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;guest:guest&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content-type:application/json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"routing_key":"orders","payload":"dummy message","payload_encoding":"string", "properties": {} }'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://localhost:15672/api/exchanges/%2f/orders/publish
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To receive messages from the queue, we can use the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;guest:guest&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;http://localhost:15672/api/queues/%2f/orders/get
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this post, we have seen how to get started with RabbitMQ. We have seen how to use the management UI, CLI and REST API to send and receive messages.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:wikipedia-rabbitmq"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/RabbitMQ"&gt;https://en.wikipedia.org/wiki/RabbitMQ&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/hands-on-rabbitmq-tutorial.html#fnref:wikipedia-rabbitmq" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:rabbitmq-cli"&gt;
&lt;p&gt;&lt;a href="https://www.rabbitmq.com/management-cli.html"&gt;https://www.rabbitmq.com/management-cli.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/hands-on-rabbitmq-tutorial.html#fnref:rabbitmq-cli" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>rabbitmq</category><category>tutorial</category><guid>https://avilpage.com/2022/12/hands-on-rabbitmq-tutorial.html</guid><pubDate>Tue, 20 Dec 2022 23:42:21 GMT</pubDate></item><item><title>Hands-on Apache Kafka | ZenTen Tutorials</title><link>https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;A short hands-on guide to get started with Apache Kafka for people who are in a hurry.&lt;/p&gt;
&lt;p&gt;In this guide, we will learn what is Apache Kafka, how to install and run it. We will also learn how to create/modify a topic and produce/consume messages from it.&lt;/p&gt;
&lt;h4&gt;What is Apache Kafka?&lt;/h4&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/kafka-overview.jpg" alt="Apache Kafka"&gt;&lt;/p&gt;
&lt;p&gt;Apache Kafka&lt;sup id="fnref:wikipedia apache kafka"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html#fn:wikipedia%20apache%20kafka"&gt;1&lt;/a&gt;&lt;/sup&gt; is a distributed event store and streaming-processing platform. It is used to
build real-time data pipelines and streaming apps. It is horizontally scalable, fault-tolerant, and has high throughput.&lt;/p&gt;
&lt;h4&gt;Kafka Terminology&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;Topic&lt;/b&gt;: A topic is a category or feed name to which records are published/consumed. It is configured with a set of
key-value pairs called topic configuration.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Producer&lt;/b&gt;: A producer is a client that publishes records to the Kafka cluster. Producers write data to topics and
partitions.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consumer&lt;/b&gt;: A consumer is a client that subscribes to topics and processes the records. Consumers read data from
topics and partitions.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consumer Group&lt;/b&gt;: A consumer group is a group of consumers that share a common purpose. Consumer groups enable a
pool of processes to divide the work of consuming and processing records.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Broker&lt;/b&gt;: A broker is a server that hosts a set of topics/partitions. It receives data from producers and sends
data to consumers.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;ZooKeeper&lt;/b&gt;: ZooKeeper is used to store the cluster configuration and the state of the cluster. All Kafka brokers
connect to ZooKeeper.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Kraft&lt;/b&gt;: Kraft(Apache Kafka Raft) is a consensus protocol that is used to manage the metadata of the Kafka cluster.
It is introduced to remove dependency on ZooKeeper.&lt;/p&gt;
&lt;h4&gt;Setting up Apache Kafka&lt;/h4&gt;
&lt;p&gt;We can use cp-all-in-one&lt;sup id="fnref:cp-all-in-one"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html#fn:cp-all-in-one"&gt;2&lt;/a&gt;&lt;/sup&gt; docker compose files to run Apache Kafka locally. This image contains all the
components of Confluent Platform including Apache Kafka, Apache Zookeeper, Confluent Schema Registry, Confluent REST
Proxy, Confluent Control Center, and others.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/confluentinc/cp-all-in-one
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cp-all-in-one/cp-all-in-one
$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;up
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Kafka CLI Tools&lt;/h4&gt;
&lt;p&gt;Kafka stores messages in topics. A topic is a category or feed name to which messages are published/consumed.&lt;/p&gt;
&lt;p&gt;Let us create a topic called &lt;code&gt;demo&lt;/code&gt; with &lt;code&gt;kafka-topics&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-topics&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--topic&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;--create&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create a topic called &lt;code&gt;demo&lt;/code&gt; with a single partition and a replication factor of 1. In multi-node cluster, we
can use &lt;code&gt;--replication-factor&lt;/code&gt;, &lt;code&gt;--partitions&lt;/code&gt; to specify the number of replicas/partitions for the topic.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-topics&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--topic&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;--partitions&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--replication-factor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--create&lt;span class="w"&gt; &lt;/span&gt;--if-not-exists
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To produce messages to a topic named &lt;code&gt;demo&lt;/code&gt;, we can use &lt;code&gt;kafka-console-producer&lt;/code&gt; and add messages to the topic:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-console-producer&lt;span class="w"&gt; &lt;/span&gt;--broker-list&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--topic&lt;span class="w"&gt; &lt;/span&gt;demo

&amp;gt;order&lt;span class="w"&gt; &lt;/span&gt;received
&amp;gt;order&lt;span class="w"&gt; &lt;/span&gt;updated
&amp;gt;order&lt;span class="w"&gt; &lt;/span&gt;shipped
&amp;gt;order&lt;span class="w"&gt; &lt;/span&gt;delivered
&amp;gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To consume messages from the same topic:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-console-consumer&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--topic&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;--from-beginning

order&lt;span class="w"&gt; &lt;/span&gt;received
order&lt;span class="w"&gt; &lt;/span&gt;updated
order&lt;span class="w"&gt; &lt;/span&gt;shipped
order&lt;span class="w"&gt; &lt;/span&gt;delivered
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since we have not defined schema for the messages, Kafka will store the messages as byte arrays. We can explicitly define the schema for the messages using Confluent Schema Registry if required.&lt;/p&gt;
&lt;p&gt;We can list all the topics in cluster using &lt;code&gt;kafka-topics&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-topics&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--list

default_ksql_processing_log
docker-connect-configs
docker-connect-offsets
docker-connect-status
demo
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To show details of a topic:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-topics&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--describe&lt;span class="w"&gt; &lt;/span&gt;--topic&lt;span class="w"&gt; &lt;/span&gt;demo

Topic:&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;TopicId:&lt;span class="w"&gt; &lt;/span&gt;7CckqkXsQXCNY0MNHYRv2w&lt;span class="w"&gt; &lt;/span&gt;PartitionCount:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;ReplicationFactor:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;Configs:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Topic:&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;Partition:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;Leader:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Replicas:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Isr:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;Offline:&lt;span class="w"&gt;         &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, all messages are stored in the topic for 7 days. We can change this retention period using &lt;code&gt;retention.ms&lt;/code&gt; configuration:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-topics&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--alter&lt;span class="w"&gt; &lt;/span&gt;--topic&lt;span class="w"&gt; &lt;/span&gt;demo&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;retention.ms&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10000&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To see all the available consumer groups, we can use &lt;code&gt;kafka-consumer-groups&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;broker&lt;span class="w"&gt; &lt;/span&gt;kafka-consumer-groups&lt;span class="w"&gt; &lt;/span&gt;--bootstrap-server&lt;span class="w"&gt; &lt;/span&gt;localhost:9092&lt;span class="w"&gt; &lt;/span&gt;--list
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Confluent Control Center&lt;/h4&gt;
&lt;p&gt;Confluent Control Center is a web UI to manage and monitor Apache Kafka.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/kafka-control-center.png" alt="Kafka Control Center"&gt;&lt;/p&gt;
&lt;p&gt;We can visit it &lt;a href="http://localhost:9021"&gt;http://localhost:9021&lt;/a&gt; and access the cluster from this UI.&lt;/p&gt;
&lt;p&gt;We can change topic configuration, view consumer groups, and monitor the cluster from this UI.&lt;/p&gt;
&lt;h4&gt;Kafka Rest Proxy&lt;/h4&gt;
&lt;p&gt;Kafka Rest Proxy&lt;sup id="fnref:kafka rest proxy"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html#fn:kafka%20rest%20proxy"&gt;3&lt;/a&gt;&lt;/sup&gt; is a RESTful interface to Apache Kafka. It provides a RESTful interface to produce
and consume messages, view the state of the cluster, and perform administrative actions without using the native Kafka
protocol or clients.&lt;/p&gt;
&lt;p&gt;To list all topics in the cluster using Kafka Rest Proxy:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8082/topics"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To get config of a topic:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8082/topics/demo"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To produce messages to a &lt;code&gt;demo&lt;/code&gt; topic with curl:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type: application/vnd.kafka.json.v2+json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"records":[{"value":{"status": "completed"}}]}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8082/topics/demo"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To consume messages from the same topic:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Accept: application/vnd.kafka.json.v2+json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8082/topics/demo"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can dynamically configure Kafka cluster settings as well.&lt;/p&gt;
&lt;p&gt;To change log level of various components of Kafka cluster using Kafka Rest Proxy.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type: application/vnd.kafka.v2+json"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{"log4j.logger.kafka.server":"DEBUG"}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8082/config"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can update the log level of various components of Kafka cluster and check the logs.&lt;/p&gt;
&lt;h4&gt;Kafka Connect&lt;/h4&gt;
&lt;p&gt;Kafka Connect is a framework to stream data between Apache Kafka and other systems. It is used to import/export data from/to Kafka.&lt;/p&gt;
&lt;p&gt;Lets use the &lt;code&gt;DataGenConnector&lt;/code&gt; to generate random data and write it to a topic.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;curl&lt;span class="w"&gt; &lt;/span&gt;--location&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'http://localhost:8083/connectors'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
--header&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
--data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{&lt;/span&gt;
&lt;span class="s1"&gt;  "name": "datagen-pageviews",&lt;/span&gt;
&lt;span class="s1"&gt;  "config": {&lt;/span&gt;
&lt;span class="s1"&gt;    "connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",&lt;/span&gt;
&lt;span class="s1"&gt;    "kafka.topic": "datagen-pageviews",&lt;/span&gt;
&lt;span class="s1"&gt;    "quickstart": "pageviews",&lt;/span&gt;
&lt;span class="s1"&gt;    "key.converter": "org.apache.kafka.connect.storage.StringConverter",&lt;/span&gt;
&lt;span class="s1"&gt;    "value.converter": "org.apache.kafka.connect.json.JsonConverter",&lt;/span&gt;
&lt;span class="s1"&gt;    "value.converter.schemas.enable": "false",&lt;/span&gt;
&lt;span class="s1"&gt;    "max.interval": 100,&lt;/span&gt;
&lt;span class="s1"&gt;    "iterations": 10000000,&lt;/span&gt;
&lt;span class="s1"&gt;    "tasks.max": "1"&lt;/span&gt;
&lt;span class="s1"&gt;  }&lt;/span&gt;
&lt;span class="s1"&gt;}&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create a connector called &lt;code&gt;datagen-pageviews&lt;/code&gt; which will generate random data and write it to a topic called &lt;code&gt;datagen-pageviews&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;KsqlDB&lt;/h4&gt;
&lt;p&gt;KsqlDB is a streaming SQL engine for Apache Kafka. It provides a SQL interface to query, transform, and analyze data in Kafka.&lt;/p&gt;
&lt;p&gt;Lets create a stream called &lt;code&gt;pageviews&lt;/code&gt; from the topic &lt;code&gt;datagen-pageviews&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8088/ksql"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type: application/vnd.ksql.v1+json; charset=utf-8"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;$'{&lt;/span&gt;
&lt;span class="s1"&gt;  "ksql": "CREATE STREAM pageviews (viewtime BIGINT, userid VARCHAR, pageid VARCHAR) WITH (KAFKA_TOPIC=\'datagen-pageviews\', VALUE_FORMAT=\'JSON\');",&lt;/span&gt;
&lt;span class="s1"&gt;  "streamsProperties": {}&lt;/span&gt;
&lt;span class="s1"&gt;}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create a table to generate viewcount per pageid:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8088/ksql"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type: application/vnd.ksql.v1+json; charset=utf-8"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;$'{&lt;/span&gt;
&lt;span class="s1"&gt;  "ksql": "CREATE TABLE pageviews_count AS&lt;/span&gt;
&lt;span class="s1"&gt;SELECT &lt;/span&gt;
&lt;span class="s1"&gt;  pageid,&lt;/span&gt;
&lt;span class="s1"&gt;  COUNT(*) AS page_views_count&lt;/span&gt;
&lt;span class="s1"&gt;FROM pageviews_stream&lt;/span&gt;
&lt;span class="s1"&gt;GROUP BY pageid&lt;/span&gt;
&lt;span class="s1"&gt;EMIT CHANGES;&lt;/span&gt;
&lt;span class="s1"&gt;",&lt;/span&gt;
&lt;span class="s1"&gt;  "streamsProperties": {}&lt;/span&gt;
&lt;span class="s1"&gt;}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can query the table to get the viewcount per pageid:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8088/ksql"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type: application/vnd.ksql.v1+json; charset=utf-8"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;$'{&lt;/span&gt;
&lt;span class="s1"&gt;  "ksql": "SELECT * FROM pageviews_count EMIT CHANGES;",&lt;/span&gt;
&lt;span class="s1"&gt;  "streamsProperties": {}&lt;/span&gt;
&lt;span class="s1"&gt;}'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how to install Apache Kafka locally using Docker. We have also seen how to produce and consume messages using Kafka console commands and Kafka Rest Proxy.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:wikipedia apache kafka"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Apache_Kafka"&gt;https://en.wikipedia.org/wiki/Apache_Kafka&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html#fnref:wikipedia%20apache%20kafka" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:cp-all-in-one"&gt;
&lt;p&gt;&lt;a href="https://github.com/confluentinc/cp-all-in-one"&gt;https://github.com/confluentinc/cp-all-in-one&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html#fnref:cp-all-in-one" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:kafka rest proxy"&gt;
&lt;p&gt;&lt;a href="https://github.com/confluentinc/kafka-rest"&gt;https://github.com/confluentinc/kafka-rest&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html#fnref:kafka%20rest%20proxy" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>kafka</category><category>tutorial</category><guid>https://avilpage.com/2022/12/hands-on-apache-kafka-tutorial.html</guid><pubDate>Sat, 17 Dec 2022 01:42:21 GMT</pubDate></item><item><title>Common Crawl on Laptop - Building Web Directory</title><link>https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;This series of posts discuss processing of common crawl dataset on laptop.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html"&gt;Extracting Subset of Common Crawl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html"&gt;Building web directory&lt;/a&gt; (this post)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In the earlier post, we have extracted all telugu web page urls to a csv file. In this post, let's explore these urls and build a web directory from it.&lt;/p&gt;
&lt;h4&gt;Explore Data&lt;/h4&gt;
&lt;p&gt;Let's see how many urls are present in the extracted subset of data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;telugu.csv
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;852025&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;telugu.csv&lt;span class="w"&gt; &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the earlier post, we have installed &lt;code&gt;duckdb&lt;/code&gt; and used it for processing parquet files. &lt;code&gt;duckdb&lt;/code&gt; can execute SQL queries directly on csv file. Let's use it to explore the data stored in telugu.csv.&lt;/p&gt;
&lt;p&gt;Let's see how many unique domains are present in the data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;    SELECT COUNT(DISTINCT url_host_name_reversed) as unique_sites&lt;/span&gt;
&lt;span class="s2"&gt;    FROM read_csv('telugu.csv', auto_detect = TRUE);&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
┌──────────────┐
│&lt;span class="w"&gt; &lt;/span&gt;unique_sites&lt;span class="w"&gt; &lt;/span&gt;│
├──────────────┤
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13632&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;│
└──────────────┘
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There ~14k unique domains. Let's see page density across these domains.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;SELECT count    AS page_count,&lt;/span&gt;
&lt;span class="s2"&gt;COUNT(*) AS sites&lt;/span&gt;
&lt;span class="s2"&gt;FROM (SELECT url_host_name_reversed, COUNT(*) AS count&lt;/span&gt;
&lt;span class="s2"&gt;FROM read_csv('te.csv', auto_detect = TRUE)&lt;/span&gt;
&lt;span class="s2"&gt;GROUP BY url_host_name_reversed) AS t&lt;/span&gt;
&lt;span class="s2"&gt;GROUP BY page_count&lt;/span&gt;
&lt;span class="s2"&gt;ORDER BY page_count;&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
┌────────────┬───────┐
│&lt;span class="w"&gt; &lt;/span&gt;page_count&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;sites&lt;span class="w"&gt; &lt;/span&gt;│
├────────────┼───────┤
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6326&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1904&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;733&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;459&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;315&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;About ~75% of the sites have less than 5 pages. It is highly unlikely that these sites complete content is in Telugu language. After manually checking a few of these sites, I found that there are a lot of false positives. &lt;/p&gt;
&lt;p&gt;In the earlier post, we have extracted all pages where there is Telugu language content. Let's filter out pages where Telugu is &lt;strong&gt;primary&lt;/strong&gt; language.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;  COPY (&lt;/span&gt;
&lt;span class="s2"&gt;    SELECT * FROM read_csv('cct.csv', auto_detect=true) &lt;/span&gt;
&lt;span class="s2"&gt;    WHERE content_languages like 'tel%'&lt;/span&gt;
&lt;span class="s2"&gt;  ) TO 'te_primary.csv' (DELIMITER ',', HEADER TRUE);&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;te_primary.csv
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;573130&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;te_primary.csv
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SELECT COUNT(DISTINCT url_host_name_reversed) as unique_sites FROM read_csv('te_primary.csv', auto_detect = TRUE)"&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;
┌──────────────┐
│&lt;span class="w"&gt; &lt;/span&gt;unique_sites&lt;span class="w"&gt; &lt;/span&gt;│
├──────────────┤
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5666&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;│
└──────────────┘&lt;span class="w"&gt;    &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's see how page density per domain has changed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;SELECT count    AS page_count,&lt;/span&gt;
&lt;span class="s2"&gt;COUNT(*) AS sites&lt;/span&gt;
&lt;span class="s2"&gt;FROM (SELECT url_host_name_reversed, COUNT(*) AS count&lt;/span&gt;
&lt;span class="s2"&gt;FROM read_csv('te_primary.csv', auto_detect = TRUE)&lt;/span&gt;
&lt;span class="s2"&gt;GROUP BY url_host_name_reversed) AS t&lt;/span&gt;
&lt;span class="s2"&gt;GROUP BY page_count&lt;/span&gt;
&lt;span class="s2"&gt;ORDER BY page_count&lt;/span&gt;
&lt;span class="s2"&gt;;&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
┌────────────┬───────┐
│&lt;span class="w"&gt; &lt;/span&gt;page_count&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;sites&lt;span class="w"&gt; &lt;/span&gt;│
├────────────┼───────┤
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2183&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;843&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;235&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;146&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;98&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;│
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Page density remains almost the same. &lt;/p&gt;
&lt;p&gt;Let's filter out sites which have at least 5 pages in Telugu. This will eliminate a lot of false positives. Let's look at the most popular sites from the results.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;Rank,Domain,Open&lt;span class="w"&gt; &lt;/span&gt;Page&lt;span class="w"&gt; &lt;/span&gt;Rank
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;,support.google.com,8.55
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;57&lt;/span&gt;,t.me,7.76
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;76&lt;/span&gt;,chrome.google.com,7.49
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;163&lt;/span&gt;,support.mozilla.org,6.99
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;170&lt;/span&gt;,groups.google.com,6.94
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A lot of unrelated domains are present here because there might be 10+ pages in telugu in these domains as well. But we don't need these.&lt;/p&gt;
&lt;p&gt;Let's look at only home page(or translated home page) where primary content language is telugu.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;  SELECT COUNT(distinct url) &lt;/span&gt;
&lt;span class="s2"&gt;  FROM read_csv('te_primary.csv', auto_detect=true) &lt;/span&gt;
&lt;span class="s2"&gt;  WHERE (url_path = '/' or url_path = '/te/') and url_query is null;&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the domain count has reduced to 6k. Let's export these domains to csv file.&lt;/p&gt;
&lt;p&gt;To categorize these domains, Common-crawl doesn't yet provide any kind of categorisation. For now, we can use Open PageRank to sort these domains based on rank. &lt;/p&gt;
&lt;p&gt;We can download top 10 million domains from Open PageRank&lt;sup id="fnref:pagerank"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html#fn:pagerank"&gt;3&lt;/a&gt;&lt;/sup&gt;. Here is a simple python script to extract telugu domains from the list.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;domains_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'domains.csv'&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domains_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;telugu_domains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;

&lt;span class="n"&gt;telugu_domains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;telugu_domains&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'t10m.csv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Domain'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;telugu_domains&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'t10m_telugu.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we have list of all telugu domains sorted by rank. In the next post, we will use this list to categorize the domains.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:common-crawl"&gt;
&lt;p&gt;&lt;a href="https://commoncrawl.org"&gt;https://commoncrawl.org&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html#fnref:common-crawl" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:columnar-index-wiki"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Column-oriented_DBMS"&gt;https://en.wikipedia.org/wiki/Column-oriented_DBMS&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html#fnref:columnar-index-wiki" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:pagerank"&gt;
&lt;p&gt;&lt;a href="https://www.domcop.com/openpagerank"&gt;https://www.domcop.com/openpagerank&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html#fnref:pagerank" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:duckdb"&gt;
&lt;p&gt;&lt;a href="https://duckdb.org"&gt;https://duckdb.org&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html#fnref:duckdb" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>command-line</category><category>common-crawl</category><category>data-analysis</category><guid>https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html</guid><pubDate>Thu, 08 Dec 2022 02:11:39 GMT</pubDate></item><item><title>Common Crawl On Laptop - Extracting Subset Of Data</title><link>https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;This series of posts discuss processing of common crawl dataset on laptop.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html"&gt;Extracting Subset of Common Crawl&lt;/a&gt; (this post)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://avilpage.com/2022/12/common-crawl-laptop-web-directory.html"&gt;Building web directory&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Common Crawl(CC)&lt;sup id="fnref:common-crawl"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html#fn:common-crawl"&gt;1&lt;/a&gt;&lt;/sup&gt; is an open repository of web containing peta bytes of data since 2008. As the dataset is huge, most of the tutorials use AWS EMR/Athena to process the data.&lt;/p&gt;
&lt;p&gt;In this post, let's learn how to extract a subset of data(entire telugu language web pages) and process it on our local machine.&lt;/p&gt;
&lt;h4&gt;Exploring Common Crawl&lt;/h4&gt;
&lt;p&gt;CC provides monthly data dumps in WARC format. Each crawl consists of about ~3 billion web pages with a compressed size of ~100 TB.&lt;/p&gt;
&lt;p&gt;In addition to WARC files, CC provides index files as well as columnar index&lt;sup id="fnref:columnar-index-wiki"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html#fn:columnar-index-wiki"&gt;2&lt;/a&gt;&lt;/sup&gt; files so that users can easily search, filter and download the data.&lt;/p&gt;
&lt;h4&gt;Common Crawl Index&lt;/h4&gt;
&lt;p&gt;Each crawl index is spread over 300 files consisting of ~250 GB of data. For this post, let use the latest crawl which is &lt;code&gt;CC-MAIN-2022-40&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The index files can be accessed from AWS S3 or https. We can use aws cli to list all the files along with the sizes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;aws&lt;span class="w"&gt; &lt;/span&gt;s3&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;--recursive&lt;span class="w"&gt; &lt;/span&gt;--human-readable&lt;span class="w"&gt; &lt;/span&gt;--summarize&lt;span class="w"&gt; &lt;/span&gt;s3://commoncrawl/cc-index/collections/CC-MAIN-2022-40
&lt;span class="m"&gt;2022&lt;/span&gt;-10-08&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:07:59&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;621&lt;/span&gt;.9&lt;span class="w"&gt; &lt;/span&gt;MiB&lt;span class="w"&gt; &lt;/span&gt;cc-index/collections/CC-MAIN-2022-40/indexes/cdx-00000.gz
&lt;span class="m"&gt;2022&lt;/span&gt;-10-08&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:08:26&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;721&lt;/span&gt;.6&lt;span class="w"&gt; &lt;/span&gt;MiB&lt;span class="w"&gt; &lt;/span&gt;cc-index/collections/CC-MAIN-2022-40/indexes/cdx-00001.gz
...
&lt;span class="m"&gt;2022&lt;/span&gt;-10-08&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:42:39&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;146&lt;/span&gt;.6&lt;span class="w"&gt; &lt;/span&gt;MiB&lt;span class="w"&gt; &lt;/span&gt;cc-index/collections/CC-MAIN-2022-40/indexes/cluster.idx
&lt;span class="m"&gt;2022&lt;/span&gt;-10-08&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;:42:33&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Bytes&lt;span class="w"&gt; &lt;/span&gt;cc-index/collections/CC-MAIN-2022-40/metadata.yaml

Total&lt;span class="w"&gt; &lt;/span&gt;Objects:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;302&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;Total&lt;span class="w"&gt; &lt;/span&gt;Size:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;236&lt;/span&gt;.1&lt;span class="w"&gt; &lt;/span&gt;GiB
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's download an index file to our local machine and see how the data is arranged. We can use &lt;code&gt;aws&lt;/code&gt; cli to download the data from s3 bucket or use wget to download it from https endpoint.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# from s3&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;aws&lt;span class="w"&gt; &lt;/span&gt;s3&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;s3://commoncrawl/cc-index/collections/CC-MAIN-2022-40/indexes/cdx-00000.gz&lt;span class="w"&gt; &lt;/span&gt;.

&lt;span class="c1"&gt;# from https&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://data.commoncrawl.org/cc-index/collections/CC-MAIN-2022-40/indexes/cdx-00000.gz
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's print top five lines of the file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;zcat&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;cdx-00000.gz&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;,1,184,137&lt;span class="o"&gt;)&lt;/span&gt;/1klikbet&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20221005193707&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"url"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://137.184.1.0/1klikbet/"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mime"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/html"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mime-detected"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/html"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"200"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"digest"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XTKGORHKLZCHDBBOMYCYYIZVRPMXNRII"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"length"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7065"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"offset"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"83437"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"filename"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"crawl-data/CC-MAIN-2022-40/segments/1664030337663.75/warc/CC-MAIN-20221005172112-20221005202112-00011.warc.gz"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"charset"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UTF-8"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"languages"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ind"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;,1,184,137&lt;span class="o"&gt;)&lt;/span&gt;/7meter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20221005192131&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"url"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://137.184.1.0/7meter/"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mime"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/html"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mime-detected"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/html"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"200"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"digest"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KUJAMRT6MXYR3RTWRJTIWJ5T2ZUB3EBH"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"length"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7456"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"offset"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"142680"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"filename"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"crawl-data/CC-MAIN-2022-40/segments/1664030337663.75/warc/CC-MAIN-20221005172112-20221005202112-00182.warc.gz"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"charset"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UTF-8"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"languages"&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ind"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
...
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last column of each line contains the language information. We can use these index files, and we can  extract all the lines containing &lt;code&gt;tel&lt;/code&gt; language code.&lt;/p&gt;
&lt;h4&gt;Columnar Index&lt;/h4&gt;
&lt;p&gt;We can also use columnar index to filter out telugu language web pages. Let's download a single file from the index.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# from s3&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;aws&lt;span class="w"&gt; &lt;/span&gt;s3&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;s3://commoncrawl/cc-index/table/cc-main/warc/crawl&lt;span class="o"&gt;=&lt;/span&gt;CC-MAIN-2022-40/subset&lt;span class="o"&gt;=&lt;/span&gt;warc/part-00000-26160df0-1827-4787-a515-95ecaa2c9688.c000.gz.parquet&lt;span class="w"&gt; &lt;/span&gt;.

&lt;span class="c1"&gt;# from https&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://data.commoncrawl.org/cc-index/table/cc-main/warc/crawl&lt;span class="o"&gt;=&lt;/span&gt;CC-MAIN-2022-40/subset&lt;span class="o"&gt;=&lt;/span&gt;warc/part-00000-26160df0-1827-4787-a515-95ecaa2c9688.c000.gz.parquet
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use Python pandas to read the parquet file and filter out telugu language web pages. Columnar index has &lt;code&gt;content_languages&lt;/code&gt; column which can be used to filter out telugu pages as shown below.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;import pandas as pd&lt;/span&gt;
&lt;span class="s2"&gt;filename = 'part-00000-26160df0-1827-4787-a515-95ecaa2c9688.c000.gz.parquet'&lt;/span&gt;
&lt;span class="s2"&gt;df = pd.read_parquet(filename)&lt;/span&gt;
&lt;span class="s2"&gt;df = df[df['content_languages'].str.startswith('tel', na=False)]&lt;/span&gt;
&lt;span class="s2"&gt;df.to_csv('telugu.csv')&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I have used Macbook M1 with local ISP(Internet Service Provider) to download and extract the index. It took around 7 minutes to download a single file and 2 minutes to extract the data. To process 300 index files, it takes ~2 days.&lt;/p&gt;
&lt;p&gt;Let's see how we can speed it up.&lt;/p&gt;
&lt;h4&gt;Improving Performance&lt;/h4&gt;
&lt;h5&gt;Faster Downloads&lt;/h5&gt;
&lt;p&gt;My Wi-Fi speed is ~4MBps when downloading the index file. To download faster, I have created t2.micro(free-tier) EC2 instance on AWS. In this machine, download speed is ~10MBps. We can use other instances, but I am trying to use only free resources. In this machine, single file download is taking ~3 minutes.&lt;/p&gt;
&lt;p&gt;CC dataset is hosted in us-east-1 region. So, I have created a new t2.micro instance in us-east-1 region. This instance is taking &amp;lt;20 seconds to download a single file. We can download entire index in less than 2 hours.&lt;/p&gt;
&lt;h5&gt;Faster Performance&lt;/h5&gt;
&lt;p&gt;To extract data from index files, we have used Python pandas without specifying the engine. By default, it uses &lt;code&gt;pyarrow&lt;/code&gt; which is a bit slow. To improve speed we can use &lt;code&gt;fastparquet&lt;/code&gt; as engine which is ~5x faster than &lt;code&gt;pyarrow&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'part-00000-26160df0-1827-4787-a515-95ecaa2c9688.c000.gz.parquet'&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_parquet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'fastparquet'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To get better performance, we can use duckdb. Duckdb is an in-process SQL OLAP DBMS and it can execute SQL queries directly on parquet files with &lt;code&gt;parquet&lt;/code&gt; extension.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;duckdb

$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'INSTALL parquet;'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can write a simple SQL query to filter out the required rows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;LOAD parquet;&lt;/span&gt;
&lt;span class="s2"&gt;COPY (select * from PARQUET_SCAN('part-00000-26160df0-1827-4787-a515-95ecaa2c9688.c000.gz.parquet') where content_languages ilike '%tel%') TO 'telugu.csv' (DELIMITER ',', HEADER TRUE);&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Duckdb can execute SQL queries on remote files as well with &lt;code&gt;httpfs&lt;/code&gt; extension.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'INSTALL httpfs;'&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;    LOAD httpfs;&lt;/span&gt;
&lt;span class="s2"&gt;    LOAD parquet;&lt;/span&gt;

&lt;span class="s2"&gt;    COPY (select * from PARQUET_SCAN('s3://commoncrawl/cc-index/table/cc-main/warc/crawl=CC-MAIN-2022-40/subset=warc/part-00001-26160df0-1827-4787-a515-95ecaa2c9688.c000.gz.parquet') where content_languages ilike '%tel%') TO 'telugu.csv' (DELIMITER ',', HEADER TRUE);"""&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Duckdb can also read series of parquet files and treat them as a single table. We can use this feature to process all the index files in a single command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;    LOAD httpfs;&lt;/span&gt;
&lt;span class="s2"&gt;    LOAD parquet;&lt;/span&gt;

&lt;span class="s2"&gt;    SET s3_region='us-east-1';&lt;/span&gt;
&lt;span class="s2"&gt;    SET s3_access_key_id='s3_secret_access_key';&lt;/span&gt;
&lt;span class="s2"&gt;    SET s3_secret_access_key='s3_secret_access_key';&lt;/span&gt;

&lt;span class="s2"&gt;    COPY (select * from PARQUET_SCAN('s3://commoncrawl/cc-index/table/cc-main/warc/crawl=CC-MAIN-2022-40/subset=warc/*.parquet') where content_languages ilike '%tel%') TO 'telugu.csv' (DELIMITER ',', HEADER TRUE);&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Depending on the file size, duckdb takes 10-15 seconds to process a single file. Since we don't need all the columns for further data processing, we can limit columns to required 5 columns.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;duckdb&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;    COPY (select url, content_languages, warc_filename, warc_record_offset, warc_record_length from PARQUET_SCAN('s3://commoncrawl/cc-index/table/cc-main/warc/crawl=CC-MAIN-2022-40/subset=warc/*.parquet') where content_languages ilike '%tel%') TO 'telugu.csv' (DELIMITER ',', HEADER TRUE);&lt;/span&gt;
&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By limiting columns&lt;sup id="fnref:cc-gg"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html#fn:cc-gg"&gt;3&lt;/a&gt;&lt;/sup&gt; there is another 65% improvement in performance. Now duckdb can process a file in 3 to 8 seconds depending on the size of the file. We can process entire index in ~20 minutes.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;With a single command, we can extract a subset of index from CC in ~2 hours. So far we have processed all files in a single process. We can also parallelize the process using &lt;code&gt;parallel&lt;/code&gt; to get faster results.&lt;/p&gt;
&lt;p&gt;In the upcoming posts, let's see how we can fetch the data from WARC files using this index and do further data processing.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:common-crawl"&gt;
&lt;p&gt;&lt;a href="https://commoncrawl.org"&gt;https://commoncrawl.org&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html#fnref:common-crawl" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:columnar-index-wiki"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Column-oriented_DBMS"&gt;https://en.wikipedia.org/wiki/Column-oriented_DBMS&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html#fnref:columnar-index-wiki" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:cc-gg"&gt;
&lt;p&gt;&lt;a href="https://groups.google.com/g/common-crawl/c/WYwkW97RM4s"&gt;https://groups.google.com/g/common-crawl/c/WYwkW97RM4s&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html#fnref:cc-gg" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>command-line</category><category>common-crawl</category><category>data-analysis</category><guid>https://avilpage.com/2022/11/common-crawl-laptop-extract-subset.html</guid><pubDate>Thu, 17 Nov 2022 01:11:39 GMT</pubDate></item><item><title>Build &amp; Distribute a Python C Extension Module</title><link>https://avilpage.com/2022/11/build-distribute-a-python-c-extension-module.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Python is a great language for prototyping and building applications. Python is an interpreted language, and it is not compiled. This means that the code is not optimized for the machine it is running on. This is where C comes in. &lt;/p&gt;
&lt;p&gt;C is a compiled language, and it is much faster than Python. So, if you want to write a Python module that is fast, you can write it in C and compile it. This is called a C extension module. In this article, we will see how to build and distribute a Python C extension module using wheels.&lt;/p&gt;
&lt;h4&gt;Building a C extension module&lt;/h4&gt;
&lt;p&gt;Let's start by creating a simple C extension module called &lt;code&gt;maths&lt;/code&gt;. In this, we will create a &lt;code&gt;square&lt;/code&gt; function that takes a number and returns its square.&lt;/p&gt;
&lt;p&gt;First, create a directory called &lt;code&gt;maths&lt;/code&gt; and create a file called &lt;code&gt;maths.c&lt;/code&gt; inside it. This is where we will write our C code.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;Python.h&amp;gt;&lt;/span&gt;


&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;py_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PyObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n_num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PyArg_ParseTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n_num&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Py_BuildValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PyMethodDef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mathsMethods&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"square"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;py_square&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;METH_VARARGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Function for calculating square in C"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;PyModuleDef&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;PyModuleDef_HEAD_INIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;"maths"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;"Custom maths module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mathsMethods&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="n"&gt;PyMODINIT_FUNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;PyInit_maths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PyModule_Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;maths&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We need to create a &lt;code&gt;setup.py&lt;/code&gt; file to build our module. This file tells Python how to build our module.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;setuptools&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Extension&lt;/span&gt;

&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"maths"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ext_modules&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"maths"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"maths.c"&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we can build our module by running &lt;code&gt;python setup.py build&lt;/code&gt;. This will create a &lt;code&gt;build&lt;/code&gt; directory with a &lt;code&gt;lib&lt;/code&gt; directory inside it.
This &lt;code&gt;lib&lt;/code&gt; directory contains our compiled module. We can import this module in Python and use it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;maths&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maths&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;25&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of testing our module by importing it in Python, we can also test it by running &lt;code&gt;python setup.py test&lt;/code&gt;. This will run the tests in the &lt;code&gt;test&lt;/code&gt; directory. We can create a &lt;code&gt;test&lt;/code&gt; directory and create a file called &lt;code&gt;test_maths.py&lt;/code&gt; inside it. This is where we will write our tests.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;unittest&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;maths&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;TestMaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maths&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Distributing a C extension module&lt;/h4&gt;
&lt;p&gt;Now that we have built our module, we can distribute it. We can distribute it as a source distribution or a binary distribution. A source distribution is a zip file that contains the source code of our module. We can distribute our module as a source distribution by running &lt;code&gt;python setup.py sdist&lt;/code&gt;. This will create a &lt;code&gt;dist&lt;/code&gt; directory with a zip file inside it. This zip file contains our source code.&lt;/p&gt;
&lt;p&gt;However, source distribution of C extension modules is not recommended. This is because the user needs to have a C compiler installed on their machine to build the module. Most users just want to &lt;code&gt;pip install&lt;/code&gt; the module and use it. So, we need to distribute our module as a binary distribution.&lt;/p&gt;
&lt;p&gt;We can use &lt;code&gt;cibuildwheel&lt;/code&gt; package to build wheels across all platforms. We can install it by running &lt;code&gt;pip install cibuildwheel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To build a wheel for a specific platform and a specific architecture, we can run &lt;code&gt;cibuildwheel --platform &amp;lt;platform&amp;gt; --architecture &amp;lt;architecture&amp;gt;&lt;/code&gt;. For example, to build a wheel for Linux x86_64, we can run &lt;code&gt;cibuildwheel --platform linux --architecture x86_64&lt;/code&gt;. This will create a &lt;code&gt;wheelhouse&lt;/code&gt; directory with a wheel file inside it. This wheel file contains our compiled module.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cibuildwheel&lt;/code&gt; runs on most CI servers. With proper workflows, we can easily get wheels for all platforms and architectures. We can then upload these wheels to PyPI and users can easily install these wheels.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we saw how to build and distribute a Python C extension module using wheels. We saw how to build a C extension module and how to distribute it as a binary distribution. We also saw how to use &lt;code&gt;cibuildwheel&lt;/code&gt; to build wheels across all platforms and architectures.&lt;/p&gt;</description><category>c</category><category>python</category><guid>https://avilpage.com/2022/11/build-distribute-a-python-c-extension-module.html</guid><pubDate>Tue, 01 Nov 2022 16:01:29 GMT</pubDate></item><item><title>Speed Up AMD64(Intel) VMs on ARM(M1 Mac) Host</title><link>https://avilpage.com/2022/10/speedup-amd64-containers-on-arm.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;From 2020, Apple has transitioned from Intel to ARM based Apple Silicon M1. If we run &lt;code&gt;uname -mp&lt;/code&gt; on these devices, we can see the CPU architecture details.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;uname&lt;span class="w"&gt; &lt;/span&gt;-mp
arm64&lt;span class="w"&gt; &lt;/span&gt;arm
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's run the same command on a device using Intel x86 processor.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;uname&lt;span class="w"&gt; &lt;/span&gt;-mp
x86_64&lt;span class="w"&gt; &lt;/span&gt;x86_64
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Many popular docker images&lt;sup id="fnref:dhub"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/10/speedup-amd64-containers-on-arm.html#fn:dhub"&gt;1&lt;/a&gt;&lt;/sup&gt; doesn't have ARM64 support yet. When setting up a dev environment in M1 Mac, there are high chances that we stumble on these containers if we are using plain docker or ARM64 VM. So, there is a need to spin up x86_64 VMs.&lt;/p&gt;
&lt;p&gt;In this article, lets see how the performance affects when running a cross architecture containers and how to speed it up.&lt;/p&gt;
&lt;h4&gt;Setup&lt;/h4&gt;
&lt;p&gt;Lima&lt;sup id="fnref:lima"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/10/speedup-amd64-containers-on-arm.html#fn:lima"&gt;2&lt;/a&gt;&lt;/sup&gt; can run foreign architecture(x6_64) VMs on Mac. Let's install lima, start a AMD64 VM &amp;amp; ARM64 VM and install k3s[^k3s] in them. k3s will run multiple process in the background and let's see how resource consumption varies in these VMs.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;lima

$&lt;span class="w"&gt; &lt;/span&gt;limactl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;linux_arm64
$&lt;span class="w"&gt; &lt;/span&gt;limactl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;linux_amd64
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When starting a VM, we can edit &lt;code&gt;arch&lt;/code&gt; parameter in the configuration. Once VM starts, we can see the details by running &lt;code&gt;limactl list&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;limactl&lt;span class="w"&gt; &lt;/span&gt;list
NAME&lt;span class="w"&gt;                &lt;/span&gt;ARCH
linux_amd64&lt;span class="w"&gt;         &lt;/span&gt;x86_64
linux_arm64&lt;span class="w"&gt;         &lt;/span&gt;aarch64
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lets login to each VM &amp;amp; install k3s.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;limactl&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;linux_arm64

$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-sfL&lt;span class="w"&gt; &lt;/span&gt;https://get.k3s.io&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;limactl&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;linux_amd64

$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-sfL&lt;span class="w"&gt; &lt;/span&gt;https://get.k3s.io&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we look at resource consumption on the host machine, x86_84 VM is using way more resources than ARM64 VM. This is because of the emulation layer that is running on top of the VM.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/arch-arm-docker.png"&gt;
&lt;/p&gt;

&lt;p&gt;We can login to individual VMs, run &lt;code&gt;top&lt;/code&gt; to see the load average as well.&lt;/p&gt;
&lt;h4&gt;Fast Mode&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;lima&lt;/code&gt; provides &lt;code&gt;fast-mode&lt;/code&gt; option for cross architecture VMs which will speed up the performance.&lt;/p&gt;
&lt;p&gt;For that, we need to log in to VMs and install emulators.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;containerd
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;nerdctl&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--privileged&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;tonistiigi/binfmt&lt;span class="w"&gt; &lt;/span&gt;--install&lt;span class="w"&gt; &lt;/span&gt;all
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After that we can restart the VMs and monitor the resource consumption. On an average, we can see that the resource consumption is reduced by 50%.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we saw how to run cross architecture VMs on M1 Mac and how to speed up the performance. We can use this technique to run cross-architecture containers on Linux as well.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:dhub"&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/search?q=&amp;amp;page=10"&gt;https://hub.docker.com/search?q=&amp;amp;page=10&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/10/speedup-amd64-containers-on-arm.html#fnref:dhub" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:lima"&gt;
&lt;p&gt;&lt;a href="https://github.com/lima-vm/lima"&gt;https://github.com/lima-vm/lima&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/10/speedup-amd64-containers-on-arm.html#fnref:lima" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>linux</category><category>macbook</category><guid>https://avilpage.com/2022/10/speedup-amd64-containers-on-arm.html</guid><pubDate>Thu, 20 Oct 2022 17:08:56 GMT</pubDate></item><item><title>Local Kubernetes Cluster with K3s on MacBook M1</title><link>https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; This article is outdated. I wrote an updated article on &lt;a href="https://avilpage.com/2023/03/setup-k8s-anywhere-k3d.html"&gt;setting up k8s anywhere with single command&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/vi5eRgBMs90" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Kubernetes(k8s)&lt;sup id="fnref:k8s"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fn:k8s"&gt;1&lt;/a&gt;&lt;/sup&gt; is an open-source system for managing large scale containerized applications. K3s&lt;sup id="fnref:k3s"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fn:k3s"&gt;2&lt;/a&gt;&lt;/sup&gt; is lightweight K8s in a single binary file. However, K3s won't work directly on Macbook as it needs systemd/OpenRC.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sfL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;k3s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;systemd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;openrc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;supervisor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k3s&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To setup k8s/k3s on Mac, we need to setup a Linux layer on top of Mac. An easy way to spin up Linux VMs on Macbook M1(Apple Silicon) is to use multipass&lt;sup id="fnref:multipass"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fn:multipass"&gt;3&lt;/a&gt;&lt;/sup&gt;. In this article, lets see how to setup K3s on Mac using multipass&lt;/p&gt;
&lt;h4&gt;K3s Setup&lt;/h4&gt;
&lt;p&gt;Install multipass with brew by running the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--cask&lt;span class="w"&gt; &lt;/span&gt;multipass
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once it is installed, spin up a new VM by specifying memory and disk space.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;launch&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;k3s&lt;span class="w"&gt; &lt;/span&gt;--mem&lt;span class="w"&gt; &lt;/span&gt;4G&lt;span class="w"&gt; &lt;/span&gt;--disk&lt;span class="w"&gt; &lt;/span&gt;40G
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once VM is launched, we can see VM details.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;k3s
Name:&lt;span class="w"&gt;           &lt;/span&gt;k3s
State:&lt;span class="w"&gt;          &lt;/span&gt;Running
IPv4:&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.64.4
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.42.0.0
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.42.0.1
Release:&lt;span class="w"&gt;        &lt;/span&gt;Ubuntu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;.04.1&lt;span class="w"&gt; &lt;/span&gt;LTS
Image&lt;span class="w"&gt; &lt;/span&gt;hash:&lt;span class="w"&gt;     &lt;/span&gt;78b5ca0da456&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Ubuntu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;.04&lt;span class="w"&gt; &lt;/span&gt;LTS&lt;span class="o"&gt;)&lt;/span&gt;
Load:&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.34&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.10&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.70
Disk&lt;span class="w"&gt; &lt;/span&gt;usage:&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.7G&lt;span class="w"&gt; &lt;/span&gt;out&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;38&lt;/span&gt;.6G
Memory&lt;span class="w"&gt; &lt;/span&gt;usage:&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.2G&lt;span class="w"&gt; &lt;/span&gt;out&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.8G
Mounts:&lt;span class="w"&gt;         &lt;/span&gt;/Users/chillaranand/test/k8s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;~/k8s
&lt;span class="w"&gt;                    &lt;/span&gt;UID&lt;span class="w"&gt; &lt;/span&gt;map:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;503&lt;/span&gt;:default
&lt;span class="w"&gt;                    &lt;/span&gt;GID&lt;span class="w"&gt; &lt;/span&gt;map:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;:default
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can even mount Mac directories on the VM.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;~/test/k8s&lt;span class="w"&gt; &lt;/span&gt;k3s:~/k8s
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will be useful when we are making changes on host directories and want to apply changes on the cluster which is inside VM.&lt;/p&gt;
&lt;p&gt;Now, we can install k3s by running the install script inside the VM.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;k3s

ubuntu@k3s:~$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-sfL&lt;span class="w"&gt; &lt;/span&gt;https://get.k3s.io&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will setup a k3s cluster on the VM. We can use kubectl and deploy applications on this cluster.&lt;/p&gt;
&lt;p&gt;By default, k3s config file will be located at &lt;code&gt;/etc/rancher/k3s/k3s.yaml&lt;/code&gt;. With this config file, we can use Lens&lt;sup id="fnref:lens"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fn:lens"&gt;4&lt;/a&gt;&lt;/sup&gt; to manage k8s cluster.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/k8s-mac-m1.jpg"&gt;
&lt;/p&gt;

&lt;p&gt;Lets find out IP of the VM &amp;amp; k8s token so that we can spin up a new VM and add it to this cluster.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# get token &amp;amp; ip of k3s&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;multipass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k3s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rancher&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;k3s&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;multipass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k3s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;grep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;launch&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;k3s-worker&lt;span class="w"&gt; &lt;/span&gt;--mem&lt;span class="w"&gt; &lt;/span&gt;2G&lt;span class="w"&gt; &lt;/span&gt;--disk&lt;span class="w"&gt; &lt;/span&gt;20G

$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;k3s-worker

ubuntu@k3s-worker:~$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-sfL&lt;span class="w"&gt; &lt;/span&gt;https://get.k3s.io&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K3S_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://192.168.64.4:6443&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K3S_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"hs48af...947fh4::server:3tfkwjd...4jed73"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can verify if the node is added correctly from k3s VM.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="nv"&gt;@k3s&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;kubectl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;
&lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ROLES&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="n"&gt;AGE&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;VERSION&lt;/span&gt;
&lt;span class="n"&gt;k3s&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;Ready&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plane&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.24.6&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;k3s1&lt;/span&gt;
&lt;span class="n"&gt;k3s&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Ready&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;none&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="n"&gt;m15s&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.24.6&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;k3s1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once we are done with experimenting k3s, we can delete the VMs.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;delete&lt;span class="w"&gt; &lt;/span&gt;k3s&lt;span class="w"&gt; &lt;/span&gt;k3s-worker
$&lt;span class="w"&gt; &lt;/span&gt;multipass&lt;span class="w"&gt; &lt;/span&gt;purge
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;multipass is a great tool to spin up Linux VMs on Mac with single command. K3s is better tool to setup k8s cluster locally for development and testing.&lt;/p&gt;
&lt;p&gt;Even though we have mentioned this tutorial is meant for Mac M1, it should work fine on any Linux distribution as well.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:k8s"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Kubernetes"&gt;https://en.wikipedia.org/wiki/Kubernetes&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fnref:k8s" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:k3s"&gt;
&lt;p&gt;&lt;a href="https://k3s.io/"&gt;https://k3s.io/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fnref:k3s" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:multipass"&gt;
&lt;p&gt;&lt;a href="https://github.com/canonical/multipass"&gt;https://github.com/canonical/multipass&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fnref:multipass" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:lens"&gt;
&lt;p&gt;&lt;a href="https://k8slens.dev/"&gt;https://k8slens.dev/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html#fnref:lens" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>kubernetes</category><category>macbook</category><guid>https://avilpage.com/2022/10/local-kubernetes-with-k3s-on-mac.html</guid><pubDate>Tue, 11 Oct 2022 02:38:36 GMT</pubDate></item><item><title>How To Root Xiamo Redmi 9 Prime Without TWRP</title><link>https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Rooting&lt;sup id="fnref:root"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fn:root"&gt;1&lt;/a&gt;&lt;/sup&gt; an android device voids warranty but gives a great control over the device. For most of the popular devices, TWRP&lt;sup id="fnref:twrp"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fn:twrp"&gt;2&lt;/a&gt;&lt;/sup&gt; recovery is available. Once a device bootloader is unlocked, we can install TWRP recovery. After that we can flash Magisk to gain root access.&lt;/p&gt;
&lt;p&gt;For some devices like Redmi 9 Prime(codename: lancelot), TWRP recovery is not available officially. There are couple of unofficial images but they are not working as expected and are causing bootloop.&lt;/p&gt;
&lt;p&gt;In this article, lets see how to root lancelot device.&lt;/p&gt;
&lt;h4&gt;Rooting Lancelot&lt;/h4&gt;
&lt;p&gt;First ensure that the device bootloader is unlocked and your system has adb &amp;amp; fastboot installed. To root without TWRP, we need to obtain patched &lt;code&gt;boot.img&lt;/code&gt; &amp;amp; &lt;code&gt;vbmeta.img&lt;/code&gt; and flash them in fastboot mode.&lt;/p&gt;
&lt;p&gt;First we need to download the stock ROM of the device to extract boot.img file. We can go to manufacturers site and download the same stock ROM&lt;sup id="fnref:lancelot"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fn:lancelot"&gt;3&lt;/a&gt;&lt;/sup&gt; that is running on the device. Once the ROM is downloaded, we can unzip it. There we can find boot.img file.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/root-redmi-9-prime.png"&gt;
&lt;/p&gt;

&lt;p&gt;We need to patch this file. To patch this, download magisk app on the device. Click on install and select the boot.img file to patch. After a few minutes, it will generate a patched boot file.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img height="440" width="220" src="https://avilpage.com/images/root-redmi-9-prime-2.jpeg"&gt;
&lt;/p&gt;

&lt;p&gt;We can download this file to system by running the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/storage/emulated/0/Download/magisk_patched-25200_cU1ws.img&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we need to download patched vbmeta file. This is available in XDA&lt;sup id="fnref:xda"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fn:xda"&gt;4&lt;/a&gt;&lt;/sup&gt; forum. Click &lt;a href="https://forum.xda-developers.com/attachments/vbmeta_redmi9-img.5082027/"&gt;this link&lt;/a&gt; to download it.&lt;/p&gt;
&lt;p&gt;Once we have both patched files, we can reboot the device in fastboot mode by using the following commands.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;devices

$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;reboot&lt;span class="w"&gt; &lt;/span&gt;bootloader
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the device is in fastboot mode, run the following commands to root it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;fastboot&lt;span class="w"&gt; &lt;/span&gt;--disable-verity&lt;span class="w"&gt; &lt;/span&gt;--disable-verification&lt;span class="w"&gt; &lt;/span&gt;flash&lt;span class="w"&gt; &lt;/span&gt;vbmeta&lt;span class="w"&gt; &lt;/span&gt;vbmeta_redmi9.img

$&lt;span class="w"&gt; &lt;/span&gt;fastboot&lt;span class="w"&gt; &lt;/span&gt;flash&lt;span class="w"&gt; &lt;/span&gt;boot&lt;span class="w"&gt; &lt;/span&gt;magisk_patched-25200_cU1ws.img

$&lt;span class="w"&gt; &lt;/span&gt;fastboot&lt;span class="w"&gt; &lt;/span&gt;reboot
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the deivce is rebooted, we can install root checker app and verify that the device is rooted successfully.&lt;/p&gt;
&lt;h4&gt;Final Thoughts&lt;/h4&gt;
&lt;p&gt;When we buy a Mac or PC(Linux/Windows), it is rooted by default. For Linux/Mac, we can run programs as sudo. For windows, we can just run a program as an administrator. There are no extra steps to root/jailbreak these devices.&lt;/p&gt;
&lt;p&gt;But most mobile companies make rooting hard and only tech savy users can root the device. It would be great if mobile phones are rooted by default.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:root"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Rooting_(Android)"&gt;https://en.wikipedia.org/wiki/Rooting_(Android)&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fnref:root" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:twrp"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/TWRP_(software)"&gt;https://en.wikipedia.org/wiki/TWRP_(software)&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fnref:twrp" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:lancelot"&gt;
&lt;p&gt;&lt;a href="https://xiaomifirmwareupdater.com/miui/lancelot/"&gt;https://xiaomifirmwareupdater.com/miui/lancelot/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fnref:lancelot" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:xda"&gt;
&lt;p&gt;&lt;a href="https://forum.xda-developers.com/t/guide-magisk-root-access-for-redmi-9-mediatek-helio-g80-without-twrp.4149531/"&gt;Guide @ XDA&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html#fnref:xda" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>android</category><category>root</category><guid>https://avilpage.com/2022/09/how-to-root-redmi-9-prime-lancelot.html</guid><pubDate>Wed, 28 Sep 2022 00:44:45 GMT</pubDate></item><item><title>Integrating Frappe Health with SNOMED CT</title><link>https://avilpage.com/2022/08/frappe-health-snomed-ct.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Frappe Health&lt;sup id="fnref:FH"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fn:FH"&gt;1&lt;/a&gt;&lt;/sup&gt; is an open-source Healthcare Information System(HIS), to efficiently manage clinics, hospitals, and other healthcare organizations. Frappe Health is built on the Frappe Framework&lt;sup id="fnref:ff"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fn:ff"&gt;2&lt;/a&gt;&lt;/sup&gt;, a low code highly customizable framework.&lt;/p&gt;
&lt;p&gt;Frappe Health provides support for integrating various medical coding standards&lt;sup id="fnref:mcs"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fn:mcs"&gt;3&lt;/a&gt;&lt;/sup&gt;. In the patient encounter doctype, doctors can search and add pre-configured medical codes.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/snomed-frappe-health1.png"&gt;&lt;/p&gt;
&lt;p&gt;In this article, let’s see how to integrate Frappe Health with SNOMED CT.&lt;/p&gt;
&lt;h4&gt;SNOMED CT Integration&lt;/h4&gt;
&lt;p&gt;SNOMED CT&lt;sup id="fnref:snomed"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fn:snomed"&gt;4&lt;/a&gt;&lt;/sup&gt; is a comprehensive collection of medical terms which helps consistent data exchange between systems. It can also cross-map to other standards like ICD-10, LOINC, etc.&lt;/p&gt;
&lt;p&gt;Since SNOMED CT is a huge dataset, it takes a lot of effort to import the entire dataset into Frappe Health. It also provides REST API to query SNOMED terms. Also, if your healthcare organization is focusing on only a specific domain, it doesn’t make sense to import the entire dataset.&lt;/p&gt;
&lt;p&gt;In such scenarios, it is better to map only the required diagnosis, symptoms, and other clinical objects.&lt;/p&gt;
&lt;p&gt;Frappe Health has a Diagnosis doctype where practitioners can enter diagnosis. We can add an additional field called &lt;code&gt;Snomed Code&lt;/code&gt; to link diagnosis to relevant SNOMED code.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/snomed-frappe-health2.png"&gt;&lt;/p&gt;
&lt;p&gt;Frappe framework provides server script&lt;sup id="fnref:ss"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fn:ss"&gt;5&lt;/a&gt;&lt;/sup&gt; to dynamically run python script on any document event. We can write a simple python script to fetch relevant SNOMED code using SNOMED REST API. This script can be executed whenever the clinical object gets modified.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/snomed-frappe-health3.png"&gt;&lt;/p&gt;
&lt;p&gt;Here is a simple python server script that adds relevant snomed codes to diagnosis.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;diagnosis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;diagnosis&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://browser.ihtsdotools.org/snowstorm/snomed-ct/browser/MAIN/descriptions?&amp;amp;limit=50&amp;amp;term="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;diagnosis&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"&amp;amp;conceptActive=true&amp;amp;lang=english&amp;amp;skipTo=0&amp;amp;returnLimit=100"&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frappe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_get_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'items'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'concept'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'items'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'concept'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'fsn'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'term'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;mc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frappe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_doc&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s1"&gt;'doctype'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Medical Code'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'code'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'medical_code_standard'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'SNOMED'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;medical_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;medical_code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After saving this script, if we go ahead and create or modify any diagnosis, it will automatically add relevant Snomed code to the diagnosis as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/snomed-frappe-health4.png"&gt;&lt;/p&gt;
&lt;p&gt;The server script makes sure all the diagnosis objects are codified automatically without any manual effort.&lt;/p&gt;
&lt;p&gt;Since Frappe Framework &amp;amp; Frappe Health are low code, extremely customizable, we are able to integrate it with SNOMED in just a few minutes. Similarly, we can codify other clinical objects like Symptoms, Procedures, Medications, etc.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:FH"&gt;
&lt;p&gt;&lt;a href="https://github.com/frappe/health"&gt;https://github.com/frappe/health&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fnref:FH" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ff"&gt;
&lt;p&gt;&lt;a href="https://frappeframework.com"&gt;https://frappeframework.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fnref:ff" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:mcs"&gt;
&lt;p&gt;&lt;a href="https://frappehealth.com/docs/v13/user/manual/en/healthcare/medical_code_standard"&gt;https://frappehealth.com/docs/v13/user/manual/en/healthcare/medical_code_standard&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fnref:mcs" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:snomed"&gt;
&lt;p&gt;&lt;a href="https://www.nlm.nih.gov/healthit/snomedct/index.html"&gt;https://www.nlm.nih.gov/healthit/snomedct/index.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fnref:snomed" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:ss"&gt;
&lt;p&gt;&lt;a href="https://frappeframework.com/docs/user/en/desk/scripting/server-script"&gt;https://frappeframework.com/docs/user/en/desk/scripting/server-script&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/08/frappe-health-snomed-ct.html#fnref:ss" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>frappe-framework</category><category>HealthIT</category><guid>https://avilpage.com/2022/08/frappe-health-snomed-ct.html</guid><pubDate>Wed, 31 Aug 2022 10:59:13 GMT</pubDate></item><item><title>Mastering DICOM - #3 Setup Modality Worklist SCP</title><link>https://avilpage.com/2022/07/dicom-modality-worklist-scp.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In the earlier article, we have learnt how to setup DICOM for digging deeper into DICOM protocol. In this article, let us learn how to setup a modality worklist(WML) SCP. Modalities can send C-FIND queries to this SCP and retrieve worklist information&lt;/p&gt;
&lt;h4&gt;Using Orthanc Worklist Plugin&lt;/h4&gt;
&lt;p&gt;Orthanc server has worklist plugin&lt;sup id="fnref:owp"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/07/dicom-modality-worklist-scp.html#fn:owp"&gt;1&lt;/a&gt;&lt;/sup&gt; which will serve worklist files that are stored in a particular directory. Let us download sample worklist files from Orthanc repository and keep in "WorklistDatabase" directory.&lt;/p&gt;
&lt;p&gt;Generate default configuration by running the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;./Orthanc&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="o"&gt;=&lt;/span&gt;config.json
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the orthanc configuration file, enable worklist plugin, specify the worklist database directory so that Orthanc can locate relevant worklist files, add required modalities and restart the server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;  "Plugins" : [
    "libModalityWorklists.dylib"
  ],

  "Worklists" : {
    "Enable": true,
    "Database": "./WorklistsDatabase",
    "FilterIssuerAet": false,
    "LimitAnswers": 0
  },

  "DicomModalities" : {
      "PYNETDICOM" : ["PYNETDICOM", "127.0.0.1", 4243],
      "FINDSCU" : ["FINDSCU", "127.0.0.1", 4244]
  }
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the plugin is enabled, we can use findscu to send C-FIND query.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;findscu&lt;span class="w"&gt; &lt;/span&gt;-W&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ScheduledProcedureStepSequence"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4242&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will retrieve all worklist files from the server.&lt;/p&gt;
&lt;h4&gt;Using wlmscpfs&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;dcmtk&lt;/code&gt; &lt;sup id="fnref:dcmtk"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/07/dicom-modality-worklist-scp.html#fn:dcmtk"&gt;2&lt;/a&gt;&lt;/sup&gt; is a collection of utilities for DICOM standard. It has &lt;code&gt;wlmscpfs&lt;/code&gt; application which implements basic Service Class Provider(SCP). We can start the service by running the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;wlmscpfs --debug --data-files-path WorklistsDatabase 4242
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the service is started modalities can send C-FIND query to this service.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We have seen how to setup MWL SCP using Orthanc &amp;amp; wmlscpfs. Now that we have PACS &amp;amp; WML SCP up and running, in the next article lets see how to dig deeper in to the dicom standard.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:owp"&gt;
&lt;p&gt;&lt;a href="https://book.orthanc-server.com/plugins/worklists-plugin.html"&gt;https://book.orthanc-server.com/plugins/worklists-plugin.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/07/dicom-modality-worklist-scp.html#fnref:owp" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:dcmtk"&gt;
&lt;p&gt;&lt;a href="https://github.com/DCMTK/dcmtk"&gt;https://github.com/DCMTK/dcmtk&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/07/dicom-modality-worklist-scp.html#fnref:dcmtk" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>dicom</category><category>HealthIT</category><guid>https://avilpage.com/2022/07/dicom-modality-worklist-scp.html</guid><pubDate>Sun, 31 Jul 2022 12:49:29 GMT</pubDate></item><item><title>Twilio Integration With Frappe Framework</title><link>https://avilpage.com/2022/06/twilio-frappe.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Frappe&lt;sup id="fnref:frappe"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/06/twilio-frappe.html#fn:frappe"&gt;1&lt;/a&gt;&lt;/sup&gt; is a low code framework for rapidly developing web applications. Twilio&lt;sup id="fnref:twilio"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/06/twilio-frappe.html#fn:twilio"&gt;2&lt;/a&gt;&lt;/sup&gt; is a SAAS platform for SMS, Video etc with APIs.&lt;/p&gt;
&lt;p&gt;In this post, lets see how to setup Twilio Integration with Frappe.&lt;/p&gt;
&lt;h4&gt;Sending SMS&lt;/h4&gt;
&lt;p&gt;Frappe has inbuilt SMS manager&lt;sup id="fnref:sms"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/06/twilio-frappe.html#fn:sms"&gt;3&lt;/a&gt;&lt;/sup&gt; where users can confgiure SMS gateway and send SMS to mobiles directly.&lt;/p&gt;
&lt;p&gt;To send out messages/SMS with Twilio, we just need to configure Twilio API keys in SMS settings.&lt;/p&gt;
&lt;p&gt;First, create an account in Twilio and collect the following information from the account.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Twilio account SID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gateway URL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Auth Token&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;"From" Phone number&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These details need to be added to SMS settings in the following format.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/frappe-twilio.png"&gt;&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;authorization&lt;/code&gt; parameter, we need to enter base64 encoded value of &lt;code&gt;account_sid:auth_token&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once these values are set, we can go to SMS Center and send out dummy messages to ensure all settings are configured properly.&lt;/p&gt;
&lt;h4&gt;Twilio App&lt;/h4&gt;
&lt;p&gt;If we want to manage incoming/outgoing voice calls or send messages via WhatsApp, we need to install &lt;code&gt;twilio-integration&lt;/code&gt;&lt;sup id="fnref:tl"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/06/twilio-frappe.html#fn:tl"&gt;4&lt;/a&gt;&lt;/sup&gt; app. We can install the app on our site by running the following commands.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;bench&lt;span class="w"&gt; &lt;/span&gt;get-app&lt;span class="w"&gt; &lt;/span&gt;https://github.com/frappe/twilio-integration.git
bench&lt;span class="w"&gt; &lt;/span&gt;--site&lt;span class="w"&gt; &lt;/span&gt;example.com&lt;span class="w"&gt; &lt;/span&gt;install-app&lt;span class="w"&gt; &lt;/span&gt;twilio_integration
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the app is installed, we can go to &lt;code&gt;Twilio Settings&lt;/code&gt; and configure the keys as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/twilio-settings.png"&gt;&lt;/p&gt;
&lt;p&gt;After that we can setup &lt;code&gt;Voice Call Settings&lt;/code&gt; to manage incoming/outgoing calls.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/twilio-voice.png"&gt;&lt;/p&gt;
&lt;p&gt;To send messages via Whatsapp, we can set the channel as &lt;code&gt;Whatsapp&lt;/code&gt; in Notification doctype.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/twilio-whatsapp.png"&gt;&lt;/p&gt;
&lt;p&gt;This is how we can send SMS, Whatsapp messages &amp;amp; manage calls via Twilio using Frappe Framework.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:frappe"&gt;
&lt;p&gt;&lt;a href="https://github.com/frappe/frappe"&gt;https://github.com/frappe/frappe&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/06/twilio-frappe.html#fnref:frappe" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:twilio"&gt;
&lt;p&gt;&lt;a href="https://www.twilio.com"&gt;https://www.twilio.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/06/twilio-frappe.html#fnref:twilio" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:sms"&gt;
&lt;p&gt;&lt;a href="https://docs.erpnext.com/docs/v13/user/manual/en/setting-up/sms-setting"&gt;https://docs.erpnext.com/docs/v13/user/manual/en/setting-up/sms-setting&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/06/twilio-frappe.html#fnref:sms" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:tl"&gt;
&lt;p&gt;&lt;a href="https://github.com/frappe/twilio-integration"&gt;https://github.com/frappe/twilio-integration&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/06/twilio-frappe.html#fnref:tl" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>frappe-framework</category><guid>https://avilpage.com/2022/06/twilio-frappe.html</guid><pubDate>Thu, 30 Jun 2022 06:16:02 GMT</pubDate></item><item><title>Why DMART is not in FNO category?</title><link>https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;FNO Segment&lt;/h4&gt;
&lt;p&gt;There are 4000+ companies&lt;sup id="fnref:wiki_nse"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:wiki_nse"&gt;1&lt;/a&gt;&lt;/sup&gt; that are traded in NSE/BSE. Of these, 198 stocks are included in FNO segement&lt;sup id="fnref:fno"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:fno"&gt;2&lt;/a&gt;&lt;/sup&gt;. For these stocks, Futures &amp;amp; Options(FNO) contracts will be available and these stocks won't have any fixed ciruit limits.&lt;/p&gt;
&lt;h4&gt;FNO Reviews&lt;/h4&gt;
&lt;p&gt;On 11th April 2018, SEBI released a circular(SEBI/HO/MRD/DP/CIR/P/2018/67) on a framework&lt;sup id="fnref:circular_framework"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:circular_framework"&gt;3&lt;/a&gt;&lt;/sup&gt; for reviewing stocks in derivatives segement. Based on this framework, a stock has to meet the below criteria be added in FNO segement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The stock shall be chosen from amongst the top 500 stocks in terms of average daily market capitalization and average daily traded value in the previous six months on a rolling basis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The stock’s median quarter-sigma order size over the last six months, on a rolling basis, shall not be less than ₹25 Lakh.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The market wide position limit(MWPL) in the stock shall not be less than ₹500 crore on a rolling basis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Average daily delivery value in the cash market shallnot be less than ₹10 crore in the previous six months on a rolling basis.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a stock is in FNO category and fails to meet this criteria, it will be removed from FNO segment.&lt;/p&gt;
&lt;p&gt;In 2021 alone, SEBI released 6 circulars thrugh which 32 new stocks are added in the FNO segment.&lt;/p&gt;
&lt;h4&gt;DMART&lt;/h4&gt;
&lt;p&gt;DMART has met the above FNO criteria long back. Even after it has met the criteria, there were more than 6 reviews&lt;sup id="fnref:c1"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:c1"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;sup id="fnref:c2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:c2"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;sup id="fnref:c3"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:c3"&gt;6&lt;/a&gt;&lt;/sup&gt; and suprisingly DMART was not added to the FNO segement.&lt;/p&gt;
&lt;p&gt;There is a long discussion on Zerodha TradingQ&amp;amp;A forum&lt;sup id="fnref:tqa"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fn:tqa"&gt;7&lt;/a&gt;&lt;/sup&gt; on why DMART was not added to FNO category but no one could give any explaination.&lt;/p&gt;
&lt;p&gt;After that, I have sent an email to SEBI &amp;amp; NSE seeking clarification for the same. It has been more than 6 months and they haven't responded yet. I have reached out to few people in the trading community privately to get clarification on the same. But nobody I know has any clue on this.&lt;/p&gt;
&lt;p&gt;I am still looking for an answer. If you can shed some light, please send out a message to me. I would like to have a quick chat with you regarding the same.&lt;/p&gt;
&lt;p&gt;Hoping to solve the mystery soon.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:wiki_nse"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/National_Stock_Exchange_of_India"&gt;https://en.wikipedia.org/wiki/National_Stock_Exchange_of_India&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:wiki_nse" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:fno"&gt;
&lt;p&gt;&lt;a href="https://www1.nseindia.com/products/content/derivatives/equities/fo_underlying_home.htm"&gt;https://www1.nseindia.com/products/content/derivatives/equities/fo_underlying_home.htm&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:fno" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:circular_framework"&gt;
&lt;p&gt;&lt;a href="https://www.sebi.gov.in/legal/circulars/apr-2018/review-of-framework-for-stocks-in-derivatives-segment_38629.html"&gt;https://www.sebi.gov.in/legal/circulars/apr-2018/review-of-framework-for-stocks-in-derivatives-segment_38629.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:circular_framework" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:c1"&gt;
&lt;p&gt;&lt;a href="https://archives.nseindia.com/content/circulars/FAOP50456.pdf"&gt;https://archives.nseindia.com/content/circulars/FAOP50456.pdf&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:c1" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:c2"&gt;
&lt;p&gt;&lt;a href="https://archives.nseindia.com/content/circulars/FAOP50414.pdf"&gt;https://archives.nseindia.com/content/circulars/FAOP50414.pdf&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:c2" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:c3"&gt;
&lt;p&gt;&lt;a href="https://archives.nseindia.com/content/circulars/FAOP50429.pdf"&gt;https://archives.nseindia.com/content/circulars/FAOP50429.pdf&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:c3" title="Jump back to footnote 6 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:tqa"&gt;
&lt;p&gt;&lt;a href="https://tradingqna.com/t/why-dmart-is-not-in-f-o/119721"&gt;https://tradingqna.com/t/why-dmart-is-not-in-f-o/119721&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html#fnref:tqa" title="Jump back to footnote 7 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>trading</category><guid>https://avilpage.com/2022/05/why-dmart-is-not-in-fno-category.html</guid><pubDate>Sun, 15 May 2022 07:14:24 GMT</pubDate></item><item><title>Using Frappe Framework As REST API Generator</title><link>https://avilpage.com/2022/04/frappe-framework-rest-api-generator.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When a company plans to build a mobile application and/or a web application, they need to create REST APIs to store data. This is a common requirement for CRUD applications.&lt;/p&gt;
&lt;p&gt;In the Python ecosystem, there are several projects like Django Rest Framework, Flask-RESTful, FastApi which does the heavy lifting of implementing REST APIs. In other ecosystems, there are similar projects/frameworks for this job.&lt;/p&gt;
&lt;h4&gt;REST API Generators&lt;/h4&gt;
&lt;p&gt;By using the above mentioned frameworks, developers can build REST APIs at a faster rate. Still, developers have to develop and maintain code for these APIs.&lt;/p&gt;
&lt;p&gt;To avoid even this work, there are REST API generators like postgrest&lt;sup id="fnref:postgrest"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/04/frappe-framework-rest-api-generator.html#fn:postgrest"&gt;1&lt;/a&gt;&lt;/sup&gt;, prest which can instantly generate REST APIs by inspecting database schema. With these, developers just have to design the DB schema and these tools take care of generating APIs without writing a single line of code.&lt;/p&gt;
&lt;p&gt;In this post, let us see how Frappe framework can be used as a REST API generator and what are the advantages of using Frappe.&lt;/p&gt;
&lt;h4&gt;Frappe Framework&lt;/h4&gt;
&lt;p&gt;Frappe framework is meta data driven low code, web framework written in Python and Javascript.&lt;/p&gt;
&lt;h5&gt;Web UI&lt;/h5&gt;
&lt;p&gt;Frappe framework provides web UI to create models(called doctypes in Frappe) and it provides REST API&lt;sup id="fnref:rest_api"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2022/04/frappe-framework-rest-api-generator.html#fn:rest_api"&gt;2&lt;/a&gt;&lt;/sup&gt; for all the models out of the box.&lt;/p&gt;
&lt;p&gt;There is no need to write manual SQL queries to manage schema. With some training even non-developers can even manage models in Frappe.&lt;/p&gt;
&lt;h5&gt;Roles &amp;amp; Permissions&lt;/h5&gt;
&lt;p&gt;With traditional API generators, managing roles &amp;amp; permissions involves additional development and maintenance costs. Frappes comes with an authentication system and it has support for role based permissions out of the box. From the web UI, users can manage roles &amp;amp; permissions.&lt;/p&gt;
&lt;h5&gt;Hooks&lt;/h5&gt;
&lt;p&gt;Even though REST API generators give API out of the box, there will be scenarios where custom business logic needs to be hooked in for various events.
In such scenarios, developers end up using an alternate framework/tool to manage hooks and business logic.&lt;/p&gt;
&lt;p&gt;Frappe provides server scripts by which arbitrary python code can be executed dynamically based on model events. There is no need to set up another framework for these things.&lt;/p&gt;
&lt;h5&gt;Utilities&lt;/h5&gt;
&lt;p&gt;Frappe framework comes with a lot of utilities like Job Queues, Schedulers, Admin interface, socket.io etc. As the project grows and the need evolves, Frappe has all the common utilities that are required for a web application development.&lt;/p&gt;
&lt;h5&gt;Conclusion&lt;/h5&gt;
&lt;p&gt;When a company wants to build a solution to a problem, it should focus most of the time in solving that problem instead of wasting their time on building CRUD interfaces or REST APIs.&lt;/p&gt;
&lt;p&gt;Frappe framework was designed to rapidly build web applications with low code. If you need a REST API generator and some additional functionality for the REST APIs, Frappe framework fits the bill and reduces a lot of development time.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:postgrest"&gt;
&lt;p&gt;&lt;a href="https://github.com/PostgREST/postgrest"&gt;https://github.com/PostgREST/postgrest&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/04/frappe-framework-rest-api-generator.html#fnref:postgrest" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:rest_api"&gt;
&lt;p&gt;&lt;a href="https://frappeframework.com/docs/user/en/api/rest"&gt;https://frappeframework.com/docs/user/en/api/rest&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2022/04/frappe-framework-rest-api-generator.html#fnref:rest_api" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>frappe-framework</category><guid>https://avilpage.com/2022/04/frappe-framework-rest-api-generator.html</guid><pubDate>Sat, 30 Apr 2022 13:31:53 GMT</pubDate></item><item><title>Adding Fuzzy Search To Frappe Framework</title><link>https://avilpage.com/2022/03/fuzzy-search-frappe-framework.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;As software developers, we use fuzzy search a lot especially when using Emacs or any other editors/IDEs. For example to search a file called &lt;code&gt;patient_history.js&lt;/code&gt;, in the editor, we can just type &lt;code&gt;pah&lt;/code&gt; and editor will narrow it down.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/frappe-fuzzy-search-1.png"&gt;&lt;/p&gt;
&lt;p&gt;This is quite handy as we can open any file with just few characters.&lt;/p&gt;
&lt;p&gt;FF is a low code, open source, web framework in Python and Javascript. All sites built with FF will have a global search bar(aka awesome bar) as shown below. Here, we can search for doctypes, reports, pages etc.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/frappe-fuzzy-search-2.png"&gt;&lt;/p&gt;
&lt;p&gt;To open &lt;code&gt;Patient History&lt;/code&gt;, we have to type almost the entire text in search bar. If we type &lt;code&gt;pah&lt;/code&gt; like we have typed in the editor, it won't show any results.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/frappe-fuzzy-search-3.png"&gt;&lt;/p&gt;
&lt;p&gt;Instead, we can add fuzzy search here so that we can search for any item with just a frew key strokes.&lt;/p&gt;
&lt;h4&gt;Fuzzy Search&lt;/h4&gt;
&lt;p&gt;There are many third party packages which implement fuzzy search in programming languages. However we can't use any of these fuzzy search packages directly. These editors internally use a scoring algorithm to rank the results and display results based on score.&lt;/p&gt;
&lt;p&gt;It internally considers many factors mentioned below for scoring.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Matched letters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CamelCase letters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;snake_case letters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consecutive matching letters&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can come up with a scoring mechanism for these factors and based on the matches, we can rank the results. I have implemented a custom fuzzy search alogirthm based on the above factors but it was slow and results were not good in some cases.&lt;/p&gt;
&lt;p&gt;Then I stumbled up this &lt;a href="https://github.com/forrestthewoods/lib_fts/blob/master/code/fts_fuzzy_match.js"&gt;fts_fuzzy_match&lt;/a&gt; implementation. This is a reverse engineered implementation of sublime text fuzzy search and it has a detailed scoring mechanism as well. It assigns negative ranking to mismatched letters and bonus points for consecutive matches.&lt;/p&gt;
&lt;p&gt;This works well and is as effective as most IDEs search. Now that there is a solid fuzzy search, all we need to do is hook this up in FF.&lt;/p&gt;
&lt;p&gt;FF internally has a fuzzy search function and we can directly hook it up here as shown here.&lt;/p&gt;
&lt;p&gt;After that, we can search for anything in just few key strokes. For example to open patient history, we can just type &lt;code&gt;pah&lt;/code&gt; and it will show results like this.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/frappe-fuzzy-search-4.png"&gt;&lt;/p&gt;
&lt;p&gt;This change is now &lt;a href="https://github.com/frappe/frappe/pull/16478"&gt;merged into Frappe framework&lt;/a&gt; and will be available in the next release.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Fuzzy search in editors/IDEs is quite handy and when we bring to other places like FF or any other search bar, it improves search experience a lot.&lt;/p&gt;</description><category>ERPNext</category><category>frappe-framework</category><category>javascript</category><guid>https://avilpage.com/2022/03/fuzzy-search-frappe-framework.html</guid><pubDate>Thu, 31 Mar 2022 16:00:33 GMT</pubDate></item><item><title>Using Frappe Framework As An Integration Engine</title><link>https://avilpage.com/2022/02/frappe-framework-mirth.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In healthcare orgainsations, data exchange between systems is complicated and has interopolabilty issues. Integration engines are widely used in healthcare industry for bi-directional data transfer.&lt;/p&gt;
&lt;p&gt;In this article, let us look at the advantages of using interface engines and how Frappe Framework can be used as an interface engine.&lt;/p&gt;
&lt;h4&gt;Integration Engines&lt;/h4&gt;
&lt;p&gt;In a traditional agile development approach, building a new interface might take weeks/months. With an integration engine, a new interface can be replicated in a matter of hours with little or no scripting at all.&lt;/p&gt;
&lt;p&gt;Creating a REST API, listening to a webhook, transforming a data between channels, broadcasting a message, sending/receiving HL7 messages or any other commonly performed task can be implemented in integration engine without much effort.&lt;/p&gt;
&lt;p&gt;Due to this integration engines like &lt;a href="https://en.wikipedia.org/wiki/Mirth_Connect"&gt;Mirth Connect&lt;/a&gt; are widely used in healthcare.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mirth-integration-engine-health.png"&gt;&lt;/p&gt;
&lt;p&gt;The above diagram shows usage of integration engine in a healthcare orgainsation.&lt;/p&gt;
&lt;h4&gt;Frappe Framework&lt;/h4&gt;
&lt;p&gt;Frappe Framework is a low code web application framework with batteries included. Even though Frappe is lablled as a framework, it can be used as an integration engine as well.&lt;/p&gt;
&lt;p&gt;It provides REST APIs out of the box for all the models(called doctypes in Frappe). Users can create custom APIs using &lt;a href="https://frappeframework.com/docs/v13/user/en/api/rest"&gt;server scripts&lt;/a&gt; and it has support for webhooks as well.&lt;/p&gt;
&lt;p&gt;Users can schedule custom cron jobs, setup emails, enable data transformations and other tasks without much coding.&lt;/p&gt;
&lt;p&gt;One feature Frappe Framework lacks when compared to integration engines is sending/receiving HL7 messages on ad-hoc ports. This feature is not available out of the box. Users need to develop a custom app or use any 3rd party app for it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/frappe/healthcare"&gt;Frappe Healthcare&lt;/a&gt; is an HIS(Healthcare Information System) built on top of Frappe/ERPNext. If a hospital is using Frappe Healthcare, then there won't be a need to use integration engine as Frappe framework can take care of most of these things.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In healthcare, integration engines are used extensively to tackle data exchange between systems. Due to its low-code development and batteries included approach, even though Frappe is a web application framework, it can be used as an integration engine as well.&lt;/p&gt;</description><category>frappe-framework</category><category>HealthIT</category><guid>https://avilpage.com/2022/02/frappe-framework-mirth.html</guid><pubDate>Mon, 28 Feb 2022 16:01:40 GMT</pubDate></item><item><title>On Resuming Writing Challenge</title><link>https://avilpage.com/2022/01/resuming-writing-challenge.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p align="center"&gt;
&lt;img height="300" width="800" src="https://avilpage.com/images/writing_challenge.jpg"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
Photo by Kaboompics on Pexels
&lt;/p&gt;

&lt;p&gt;In 2018, I decided to write at least one blog post per month throughout the year. Even though I tried to write posts every month, I couldn't publish anything in few months.&lt;/p&gt;
&lt;p&gt;In 2019, I went a step ahead and made a legal(?) agreement with a friend. I paid him 1,00,000 rupees (~1,200$) and told him that he could keep the money as a reward if I failed to write a blog post every month.&lt;/p&gt;
&lt;p&gt;This agreement kept me on my toes. I didn't miss writing a single month in 2019. I stayed awake on the last days of the month to finish and publish the post before midnight.&lt;/p&gt;
&lt;p&gt;In 2020, I took up the challenge again and I was able to write at least one post every month.&lt;/p&gt;
&lt;p&gt;In 2021, I didn't take up the challenge. I wrote just three posts in the entire year.&lt;/p&gt;
&lt;p&gt;In the two years when I took the challenge, even though I wrote a few mediocre articles, I wrote a few good articles. In the other two years when I didn't take the challenge, my writing quality and quantity declined.&lt;/p&gt;
&lt;p&gt;Due to this, I decided to take up the writing challenge again this year.&lt;/p&gt;
&lt;p&gt;Instead of limiting the 1,00,000 reward to my friend, I decided to extend it to all the readers.&lt;/p&gt;
&lt;p&gt;The first person who calls out that there is no new blog post in a month will get the 1,00,000 reward. The next three people will get a small gift as a token of appreciation.&lt;/p&gt;
&lt;p&gt;I will try my best to write at least one post every month. Let's wait till the end of the year and see how it goes.&lt;/p&gt;</description><category>musings</category><guid>https://avilpage.com/2022/01/resuming-writing-challenge.html</guid><pubDate>Wed, 19 Jan 2022 00:36:06 GMT</pubDate></item><item><title>A Typo Got Me $100 Bug Bounty</title><link>https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;On a lazy evening, while on a call with a friend, I made a typo while entering the url. Instead of typing &lt;a href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html"&gt;http://app-00421.on-aptible.com&lt;/a&gt;, I typed &lt;a href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html"&gt;http://app-00412.on-aptible.com&lt;/a&gt;&lt;sup id="fnref:aptible"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fn:aptible"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;In this article, lets see how this typing mistake got me a bug bounty.&lt;/p&gt;
&lt;h4&gt;Vulnerability&lt;/h4&gt;
&lt;p&gt;A &lt;a href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html"&gt;bug bounty program&lt;/a&gt;&lt;sup id="fnref:bb"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fn:bb"&gt;2&lt;/a&gt;&lt;/sup&gt; is a deal offered by companies by which individuals can receive recognition and compensation for reporting bugs, security exploits and vulnerabilities.&lt;/p&gt;
&lt;p&gt;Aptible provides HIPAA&lt;sup id="fnref:hipaa"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fn:hipaa"&gt;3&lt;/a&gt;&lt;/sup&gt; compliant PAAS platform so that healthcare companies can deploy their apps without compliance hassle.&lt;/p&gt;
&lt;p&gt;After deploying an application on aptible, users can create an endpoint for public access. For this purpose, atpible generates domain names in sequential order.&lt;/p&gt;
&lt;p&gt;Due to this, a set of publicly exposed servers will have incremental domain names. A lot of companies use these sequentially generated domain names for staging &amp;amp; testing purposes. In general, many companies don't bother about implementing security best practices on non-production servers.&lt;/p&gt;
&lt;p&gt;When I was trying to access a demo site at &lt;a href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html"&gt;http://app-00421.on-aptible.com&lt;/a&gt;, I made a typo and visited &lt;a href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html"&gt;http://app-00412.on-aptible.com&lt;/a&gt;. This site was a staging site of some other company without any authentication. The company's source code, AWS keys and a lot of sensitive information was publicly accessible.&lt;/p&gt;
&lt;p&gt;I quickly emailed that company regarding this issue and they took their site offline. As per &lt;a href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html"&gt;Aptible disclosure policy&lt;/a&gt;&lt;sup id="fnref:disclosure"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fn:disclosure"&gt;4&lt;/a&gt;&lt;/sup&gt;, this bug is out of scope. Howev er, I sent an email to their team regarding the severity of the issue. Since sequential domain names are generating additional target surface for attackers, I suggested to move to random urls.&lt;/p&gt;
&lt;p&gt;For this disclosure, they have provided a bounty of 100$ and Aptible decided to move away from sequential domain names.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:aptible"&gt;
&lt;p&gt;URL has been changed for anonymity. &lt;a class="footnote-backref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fnref:aptible" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:bb"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Bug_bounty_program"&gt;https://en.wikipedia.org/wiki/Bug_bounty_program&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fnref:bb" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:hipaa"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act"&gt;HIPAA - Wikipedia&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fnref:hipaa" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:disclosure"&gt;
&lt;p&gt;&lt;a href="https://www.aptible.com/legal/responsible-disclosure/"&gt;https://www.aptible.com/legal/responsible-disclosure/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html#fnref:disclosure" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>HealthIT</category><category>musings</category><category>security</category><guid>https://avilpage.com/2021/10/typo-lead-to-bug-bounty.html</guid><pubDate>Mon, 25 Oct 2021 03:22:19 GMT</pubDate></item><item><title>MacBook Productivity Tools For Developers</title><link>https://avilpage.com/2021/06/lesser-know-useful-utilities-for-mac.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When using Mac, there are few utilities which come in handy for day to day operations and also aid in productivity.&lt;/p&gt;
&lt;p&gt;Here are some of the useful but lesser know utilities for mac.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Alfred&lt;/h4&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/mac-alfred.png" alt="Alfred"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://alfredapp.com"&gt;Alfred&lt;/a&gt; is a productivity app for Mac which helps you to search and launch apps, files, bookmarks, and more. You can also search the web and do calculations.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Bandwidth+&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/bandwidth.png"&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/us/app/bandwidth/id490461369?mt=12"&gt;Bandwidth+&lt;/a&gt; tracks network usage on Mac. If there are multiple networks, it gives detailed information about the network consumed on all the networks.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;CheatSheet&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/cheatsheet.png"&gt;
&lt;/p&gt;

&lt;p&gt;Ever wondered what are the keybindings when using any application? With &lt;a href="https://www.mediaatelier.com/CheatSheet/"&gt;CheatSheet&lt;/a&gt;, we can just hold &lt;code&gt;⌘&lt;/code&gt; key bit longer, and it will show all the available shortcuts in the application.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Debokee Tools&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/debokee.png"&gt;
&lt;/p&gt;

&lt;p&gt;Wondering which network your Mac connected to? If you use multiple wireless networks, then &lt;a href="https://apps.apple.com/us/app/debookee-tools/id1110355801?mt=12"&gt;Debokee Tools&lt;/a&gt; can show the connected wireless network name directly in the menu bar.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Espanso&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/espanso.gif"&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/federico-terzi/espanso"&gt;Espanso&lt;/a&gt; is a text expanding tool that improves productivity across the system. We can set up shortcuts for frequently typed things like email, phone number etc., so that we don't have to type them again and again.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Flycut&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/TermiT/Flycut"&gt;Flycut&lt;/a&gt; is a simple clipboard manager, stores history. When you want to copy/paste frequently, this comes in handy.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Grand Perspective&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/grand_perspective.jpg"&gt;
&lt;/p&gt;

&lt;p&gt;If Mac is running low on disk space, &lt;a href="https://apps.apple.com/us/app/grandperspective/id1111570163"&gt;Grand Perspective&lt;/a&gt; shows a graphical view of the disk usage. It will be much easier to pinpoint large files that are consuming the disk and then clean them up.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Hotkey&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/mac-hotkey.png"&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/app/hotkey-app/id975890633"&gt;Hotkey&lt;/a&gt; is a simple app that allows you to set up global shortcuts for frequently used actions. It can be used to open applications, folders, websites, and more.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Karabiner-Elements&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://karabiner-elements.pqrs.org/"&gt;Karabiner Elements&lt;/a&gt; allows users to customize keyboard via simple modifications, complex modifications, function key modifications etc.&lt;/p&gt;
&lt;p&gt;We can use space bar as space and control as well with a simple &lt;a href="https://github.com/ChillarAnand/init/blob/main/karabiner_space_control.json"&gt;modification rule&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Stats&lt;/h4&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/mac-stats.png"&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/exelban/stats"&gt;Stats&lt;/a&gt; is a simple app that shows the CPU, memory, disk, and network usage in the menu bar. It also shows the temperature of the CPU.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;These are some useful utilities for day to day usage. In the upcoming articles, lets learn about useful command line utilities that improve productivity on a daily basis.&lt;/p&gt;</description><category>macbook</category><guid>https://avilpage.com/2021/06/lesser-know-useful-utilities-for-mac.html</guid><pubDate>Fri, 11 Jun 2021 02:30:00 GMT</pubDate></item><item><title>Mastering DICOM - #2 Setup Orthanc DICOM Server</title><link>https://avilpage.com/2021/03/setup-orthanc-demo-server.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;This is a series of &lt;a href="https://avilpage.com/tags/dicom.html"&gt;articles on mastering Dicom&lt;/a&gt;. In the earlier article, we have learnt how PACS/DICOM simplifies the clinical work flow.&lt;/p&gt;
&lt;p&gt;In this article, lets setup a dicom server so that we have a server to play around with Dicom files.&lt;/p&gt;
&lt;h4&gt;Orthanc Server&lt;/h4&gt;
&lt;p&gt;There are several Dicom servers like Orthanc, Dicoogle etc. &lt;a href="https://en.wikipedia.org/wiki/Orthanc_(server)"&gt;Orthanc&lt;/a&gt; is a lightweight open source dicom server and is widely used by many Health care organisations.&lt;/p&gt;
&lt;p&gt;Sébastien Jodogne, original author of Orthanc maintains docker images. We can use these images to run Orthanc server locally.&lt;/p&gt;
&lt;p&gt;Ensure docker is installed on the machine and then run the following command to start Orthanc server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4242&lt;/span&gt;:4242&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8042&lt;/span&gt;:8042&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;jodogne/orthanc-python
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the server is started, we can visit &lt;a href="http://localhost:8042"&gt;http://localhost:8042&lt;/a&gt; and explore Orthanc server.&lt;/p&gt;
&lt;h4&gt;Heroku Deployment&lt;/h4&gt;
&lt;p&gt;Heroku is PAAS platform which supports docker deployments. Lets deploy Orthac server to Heroku for testing.&lt;/p&gt;
&lt;p&gt;By default, Orthanc server runs on 8042 port as defined in the config file. Heroku dynamically assigns port for the deployed process.&lt;/p&gt;
&lt;p&gt;We can write a shell script which will read port number from environment variable, replace it in Orthanc configuration file and then start Orthanc server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#! /bin/sh&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-x

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;

sed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'s/ : 8042/ : '&lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;&lt;span class="s1"&gt;'/g'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;/etc/orthanc/orthanc.json

Orthanc&lt;span class="w"&gt; &lt;/span&gt;/etc/orthanc/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use this shell script as entry point in docker as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;FROM jodogne/orthanc-python

EXPOSE $PORT

WORKDIR /app
ADD . /app

ENTRYPOINT [ "./run.sh" ]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create a new app in heroku and we can deploy this container.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;heroku&lt;span class="w"&gt; &lt;/span&gt;apps:create&lt;span class="w"&gt; &lt;/span&gt;orthanc-demo

$&lt;span class="w"&gt; &lt;/span&gt;heroku&lt;span class="w"&gt; &lt;/span&gt;container:push&lt;span class="w"&gt; &lt;/span&gt;web
$&lt;span class="w"&gt; &lt;/span&gt;heroku&lt;span class="w"&gt; &lt;/span&gt;container:release&lt;span class="w"&gt; &lt;/span&gt;web
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the deployment is completed, we can access our app from the endpoint provided by heroku. Here is a &lt;a href="https://orthanc-demo.herokuapp.com"&gt;orthanc demo server&lt;/a&gt; running on heroku.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have learnt how to setup Orthanc server and deployed it to Heroku. In the next article, let dig deeper into dicom protocol by upload/accessing dicom files to the server.&lt;/p&gt;</description><category>dicom</category><category>HealthIT</category><guid>https://avilpage.com/2021/03/setup-orthanc-demo-server.html</guid><pubDate>Fri, 26 Mar 2021 00:30:00 GMT</pubDate></item><item><title>Minimum Viable Testing - Get Maximum Stability With Minimum Effort</title><link>https://avilpage.com/2020/12/minimum-viable-testing-risk-based.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Even though Test Driven Development(TDD)&lt;sup id="fnref:tdd"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/12/minimum-viable-testing-risk-based.html#fn:tdd"&gt;1&lt;/a&gt;&lt;/sup&gt; saves time &amp;amp; money in the long run, there are many excuses why developers don't test the software. In this article, lets look at Minimum Viable Testing(aka Risk-Based Testing)&lt;sup id="fnref:mvt"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/12/minimum-viable-testing-risk-based.html#fn:mvt"&gt;2&lt;/a&gt;&lt;/sup&gt; and how it helps to achieve maximum stability with minimum effort.&lt;/p&gt;
&lt;h4&gt;Minimum Viable Testing&lt;/h4&gt;
&lt;p&gt;Pareto principle states that 80% of consequences come from 20% of the causes. In software proucts, 80% of the users use 20% of the features. A bug in these 20% features is likely to cause higher impact than the rest. It makes sense to prioritize testing of these features than the rest.&lt;/p&gt;
&lt;p&gt;Assessing the importance of a feature or risk of a bug depends on the product that we are testing. For example, in a project a paid feature gets more importance than free feature.&lt;/p&gt;
&lt;p&gt;In TDD, we start with writing tests and then writing code. Compared to TDD, MVT consumes less time. When it comes to testing, there are unit tests, integration tests, snapshot tests, ui tests and so on.&lt;/p&gt;
&lt;p&gt;When getting started with testing, it is important to have integration tests in place to make sure if something is working. Also the cost of integration tests is much cheaper compared to unit tests.&lt;/p&gt;
&lt;p&gt;Most of the SAAS products have a web/mobile application and an API server to handle requests for the front end applications. Having UI tests for the applications and integration tests for APIs for the most crucial functionality should cover the ground. This will make sure any new code that is being pushed doesnt break the core functionality.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Even though RBT helps with building a test suite quicker that TDD, it should be seen as an alternate option to TDD. We should see RBT as a starting point for testing from which we can take next step towards achieving full stability for the product.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:tdd"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;https://en.wikipedia.org/wiki/Test-driven_development&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/12/minimum-viable-testing-risk-based.html#fnref:tdd" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:mvt"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Risk-based_testing"&gt;https://en.wikipedia.org/wiki/Risk-based_testing&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/12/minimum-viable-testing-risk-based.html#fnref:mvt" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>testing</category><guid>https://avilpage.com/2020/12/minimum-viable-testing-risk-based.html</guid><pubDate>Thu, 31 Dec 2020 13:53:11 GMT</pubDate></item><item><title>Find Performance Issues In Web Apps with Sentry</title><link>https://avilpage.com/2020/11/python-web-applications-performance-sentry.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Earlier, we have seen couple of articles here on finding performance issues&lt;sup id="fnref:perf1"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fn:perf1"&gt;1&lt;/a&gt;&lt;/sup&gt; and how to go about optimizing them&lt;sup id="fnref:perf2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fn:perf2"&gt;2&lt;/a&gt;&lt;/sup&gt;. In this article, lets see how to use Sentry Performance to find bottlenecks in Python web applications.&lt;/p&gt;
&lt;h4&gt;The Pitfalls&lt;/h4&gt;
&lt;p&gt;A common pitfall while identifying performance issues is to do profiling in development environment. Performance in development environment will be quite different from production environment due to difference in system requirements, database size, network latency etc.&lt;/p&gt;
&lt;p&gt;In some cases, performance issues could be happening only for certain users and in specific scenarios.&lt;/p&gt;
&lt;p&gt;Replicating production performance on development machine will be costly. To avoid these, we can use APM tool to monitor performance in production.&lt;/p&gt;
&lt;h4&gt;Sentry Performance&lt;/h4&gt;
&lt;p&gt;Sentry is widely used Open source error tracking tool. Recently, it has introduced Performance to track performance also. Sentry doesn't need any agent running on the host machine to track performance. Enabling performance monitoring is just a single line change in Sentry&lt;sup id="fnref:sentry"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fn:sentry"&gt;3&lt;/a&gt;&lt;/sup&gt; setup.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sentry_sdk&lt;/span&gt;


&lt;span class="n"&gt;sentry_sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;dsn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"dummy_dsn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Trace half the requests&lt;/span&gt;
    &lt;span class="n"&gt;traces_sample_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Tracing performance will have additional overhead&lt;sup id="fnref:oh"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fn:oh"&gt;4&lt;/a&gt;&lt;/sup&gt; on the web application response time. Depending on the traffic, server capacity, acceptable overhead, we can decide what percentage of the requests we need to trace.&lt;/p&gt;
&lt;p&gt;Once performance is enabled, we can head over to Sentry web application and see traces for the transactions along with operation breakdown as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/sentry0.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;At a glance, we can see percentage of time spent across each component which will pinpoint where the performance problem lies.&lt;/p&gt;
&lt;p&gt;If the app server is taking most of the time, we can explore the spans in detail to pinpoint the exact line where it is taking most time. If database is taking most of the time, we can look out for the number of queries it is running and slowest queries to pinpoint the problem.&lt;/p&gt;
&lt;p&gt;Sentry also provides option to set alerts when there are performance. For example, when the response time for a duration are less than a limit for a specified duration, Sentry can alert developers via email, slack or any other integration channels.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;There are paid APM tools like New Relic, AppDynamics which requires an agent to be installed on the server. As mentioned in earlier articles, there are open source packages like django-silk to monitor performance. It will take time to set up these tools and pinpoint the issue.&lt;/p&gt;
&lt;p&gt;Sentry is the only agentless APM tool&lt;sup id="fnref:note"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fn:note"&gt;5&lt;/a&gt;&lt;/sup&gt; available for Python applications. Setting up Sentry performance is quite easy and performance issues can be pinpointed without much hassle.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:perf1"&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2018/12/django-bottleneck-performance-scaling.html"&gt;Finding High-impact Performance Bottlenecks&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fnref:perf1" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:perf2"&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2019/08/django-profile-optimize-views.html"&gt;Optimizing Bottlenecks In Django&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fnref:perf2" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:sentry"&gt;
&lt;p&gt;&lt;a href="https://docs.sentry.io/platforms/python/performance/"&gt;Sentry - Performance Monitoring&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fnref:sentry" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:oh"&gt;
&lt;p&gt;&lt;a href="https://github.com/getsentry/sentry-python/issues/668#issuecomment-707768485"&gt;Sentry has 8% overhead in Django test suite&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fnref:oh" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:note"&gt;
&lt;p&gt;Earlier there was Opbeat APM which is now shutdown due to acquistion by Elastic. &lt;a class="footnote-backref" href="https://avilpage.com/2020/11/python-web-applications-performance-sentry.html#fnref:note" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>profiling</category><category>python</category><category>sentry</category><guid>https://avilpage.com/2020/11/python-web-applications-performance-sentry.html</guid><pubDate>Mon, 30 Nov 2020 18:29:54 GMT</pubDate></item><item><title>Make Python Docker Builds Slim &amp; Fast</title><link>https://avilpage.com/2020/10/python-docker-build-slim-fast.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When using Docker, if the build is taking time or the build image is huge, it will waste system resources as well as our time. In this article, let's see how to reduce build time as well as image size when using Docker for Python projects.&lt;/p&gt;
&lt;h4&gt;Project&lt;/h4&gt;
&lt;p&gt;Let us take a hello world application written in flask.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;flask&lt;/span&gt;


&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'hello world - v1.0.0'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's create a requirements.txt file to list out python packages required for the project.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;flask==1.1.2
pandas==1.1.2
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pandas binary wheel size is ~10MB. It is included in requirements to see how python packages affect docker image size.&lt;/p&gt;
&lt;p&gt;Here is our Dockerfile to run the flask application.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;FROM python:3.7

ADD . /app

WORKDIR /app

RUN python -m pip install -r requirements.txt

EXPOSE 5000

ENTRYPOINT [ "python" ]

CMD [ "-m" "flask" "run" ]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's use the following commands to measure the image size &amp;amp; build time with/without cache.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;flask:0.0&lt;span class="w"&gt; &lt;/span&gt;--pull&lt;span class="w"&gt; &lt;/span&gt;--no-cache
&lt;span class="o"&gt;[&lt;/span&gt;+&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Building&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;.3s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;/9&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;FINISHED

$&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;app.py&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# modify app.py file&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;flask:0.1
&lt;span class="o"&gt;[&lt;/span&gt;+&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Building&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;.3s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;/9&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;FINISHED

$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;images&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;flask
flask&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.1&lt;span class="w"&gt;     &lt;/span&gt;06d3e985f12e&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.01GB
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the current docker, here are the results.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/docker0.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;h4&gt;1. Install requirements first&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;FROM python:3.7

WORKDIR /app

ADD ./requirements.txt /app/requirements.txt

RUN python -m pip install -r requirements.txt

ADD . /app

EXPOSE 5000

ENTRYPOINT [ "python" ]

CMD [ "-m" "flask" "run" ]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let us modify the docker file to install requirements first and then add code to the docker image.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/docker1.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;Now, build without cache took almost the same time. With cache, the build is completed in a second. Since docker caches step by step, it has cached python package installation step and thereby reducing the build time.&lt;/p&gt;
&lt;h4&gt;2. Disable Cache&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;FROM python:3.7

WORKDIR /app

ADD ./requirements.txt /app/requirements.txt

RUN python -m pip install -r requirements.txt --no-cache

ADD . /app

EXPOSE 5000

ENTRYPOINT [ "python" ]

CMD [ "-m" "flask" "run" ]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, pip will cache the downloaded packages. Since we don't need a cache inside docker, let's disable pip cache by passing &lt;code&gt;--no-cache&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/docker2.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;This reduced the docker image size by ~20MB. In real-world projects, where there are a good number of dependencies, the overall image size will be reduced a lot.&lt;/p&gt;
&lt;h4&gt;3. Use slim variant&lt;/h4&gt;
&lt;p&gt;Till now, we have been using defacto Python variant. It has a large number of common debian packages. There is a slim variant that doesn't contain all these common packages&lt;sup id="fnref:dpy"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fn:dpy"&gt;4&lt;/a&gt;&lt;/sup&gt;. Since we don't need all these debian packages, let's use slim variant.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;FROM python:3.7-slim

...
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src="https://avilpage.com/images/docker3.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;This reduced the docker image size by ~750 MB without affecting the build time.&lt;/p&gt;
&lt;h4&gt;4. Build from source&lt;/h4&gt;
&lt;p&gt;Python packages can be installed via wheels (.whl files) for a faster and smoother installation. We can also install them via source code. If we look at Pandas project files on PyPi&lt;sup id="fnref:pandas"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fn:pandas"&gt;1&lt;/a&gt;&lt;/sup&gt;, it provides both wheels as well as tar zip source files. Pip will prefer wheels over source code the installation process will be much smoother.&lt;/p&gt;
&lt;p&gt;To reduce Docker image size, we can build from source instead of using the wheel. This will increase build time as the python package will take some time to compile while building.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src="https://avilpage.com/images/docker4.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;Here build size is reduced by ~20MB but the build has increased to 15 minutes.&lt;/p&gt;
&lt;h4&gt;5. Use Alpine&lt;/h4&gt;
&lt;p&gt;Earlier we have used, python slim variant the base image. However, there is Alpine variant which is much smaller than slim. One caveat with using alpine is Python wheels won't work with this image&lt;sup id="fnref:aw"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fn:aw"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;We have to build all packages from source. For example, packages like TensorFlow provide only wheels for installation. To install this on Alpine, we have to install from the source which will take additional effort to figure out dependencies and install.&lt;/p&gt;
&lt;p&gt;Using Alpine will reduce the image size by ~70 MB but it is not recomended to use Alpine as wheels won't work with this image.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/docker5.png" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;All the docker files used in the article are available on github&lt;sup id="fnref:gh"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fn:gh"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We have started with a docker build of 1.01 GB and reduced it to 0.13 GB. We have also optimized build times using the docker caching mechanism. We can use appropriate steps to optimize build for size or speed or both.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:pandas"&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/pandas/#files"&gt;https://pypi.org/project/pandas/#files&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fnref:pandas" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:aw"&gt;
&lt;p&gt;&lt;a href="https://github.com/docker-library/docs/issues/904"&gt;https://github.com/docker-library/docs/issues/904&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fnref:aw" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:gh"&gt;
&lt;p&gt;&lt;a href="https://github.com/ChillarAnand/library-docker"&gt;https://github.com/ChillarAnand/library-docker&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fnref:gh" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:dpy"&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/_/python"&gt;https://hub.docker.com/_/python&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/10/python-docker-build-slim-fast.html#fnref:dpy" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>devops</category><category>featured</category><category>python</category><guid>https://avilpage.com/2020/10/python-docker-build-slim-fast.html</guid><pubDate>Sat, 31 Oct 2020 12:53:13 GMT</pubDate></item><item><title>How To Deploy Mirth Connect To Kubernetes</title><link>https://avilpage.com/2020/07/deploy-mirth-to-kubernetes.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;NextGen Connect(previously Mirth Connect) is widely used integration engine for information exchange in health-care domain. In this article, let us see how to deploy Mirth Connect to a Kubernetes cluster.&lt;/p&gt;
&lt;h4&gt;Deployment To k8s&lt;/h4&gt;
&lt;p&gt;From version 3.8, NextGen has started providing official docker images for Connect&lt;sup id="fnref:nc"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/07/deploy-mirth-to-kubernetes.html#fn:nc"&gt;1&lt;/a&gt;&lt;/sup&gt;. By default, Connect docker exposes 8080, 8443 ports. We can start a Connect instance locally, by running the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;$docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;:8080&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8443&lt;/span&gt;:8443&lt;span class="w"&gt; &lt;/span&gt;nextgenhealthcare/connect
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use this docker image and create a k8s deployment to start a container.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mirth-connect
  namespace: default
spec:
  template:
    spec:
      containers:
      &lt;span class="k"&gt;-&lt;/span&gt; name: mirth-connect
        image: docker.io/nextgenhealthcare/connect
        ports:
        &lt;span class="k"&gt;-&lt;/span&gt; name: http
          containerPort: 8080
        &lt;span class="k"&gt;-&lt;/span&gt; name: https
          containerPort: 8443
        &lt;span class="k"&gt;-&lt;/span&gt; name: hl7-test
          containerPort: 9001
        env:
          &lt;span class="k"&gt;-&lt;/span&gt; name: DATABASE
            value: postgres
          &lt;span class="k"&gt;-&lt;/span&gt; name: DATABASE_URL
            value: jdbc:postgresql://avilpage.com:5432/mirth_db
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This deployment file can be applied on a cluster using &lt;code&gt;kubectl&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;connect-deployment.yaml
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To access this container, we can create a service to expose this deployment to public.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;
&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;
&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mirth&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;balancer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;acm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ap&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;south&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;balancer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"443"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;external&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LoadBalancer&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mirth&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8443&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hl7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9001&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9001&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TCP&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create a load balancer in AWS through which we can access mirth connect instance. If an ingress controller is present in the cluster, we can use it directly instead of using a seperate load balancer for this service.&lt;/p&gt;
&lt;p&gt;Once Mirth Connect is up &amp;amp; running, we might have to create HL7 channels running on various ports. In the above configuration files, we have exposed 9001 HL7 port for testing of channel. Once we configure Mirth Channels, we need to expose appropriate ports in deployment as well as service similiar to this.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Earlier, there were no official docker images for Mirth Connect and it was bit diffucult to dockerize Mirth Connect and deploy it. With the release of official Docker images, deploying Mirth Connect to k8s or any other container orchestration platform has become much easier.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:nc"&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/r/nextgenhealthcare/connect/"&gt;https://hub.docker.com/r/nextgenhealthcare/connect/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/07/deploy-mirth-to-kubernetes.html#fnref:nc" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>aws</category><category>devops</category><category>HealthIT</category><category>kubernetes</category><guid>https://avilpage.com/2020/07/deploy-mirth-to-kubernetes.html</guid><pubDate>Wed, 30 Sep 2020 17:55:46 GMT</pubDate></item><item><title>Serial Bluetooth Terminal With Python Asyncio</title><link>https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;PySerial package provides a tool called miniterm&lt;sup id="fnref:miniterm"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fn:miniterm"&gt;1&lt;/a&gt;&lt;/sup&gt;, which provides a terminal to interact with any serial ports.&lt;/p&gt;
&lt;p&gt;However miniterm sends each and every character as we type instead of sending entire message at once. In addition to this, it doesn't provide any timestamps on the messages transferred.&lt;/p&gt;
&lt;p&gt;In this article, lets write a simple terminal to address the above issues.&lt;/p&gt;
&lt;h4&gt;Bluetooth Receiver&lt;/h4&gt;
&lt;p&gt;pyserial-asyncio&lt;sup id="fnref:pyserial-asyncio"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fn:pyserial-asyncio"&gt;2&lt;/a&gt;&lt;/sup&gt; package provides Async I/O interface for communicating with serial ports. We can write a simple function to read and print all the messages being received on a serial port as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;datetime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;dt&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;serial_asyncio&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readuntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; Rx &amp;lt;== &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;serial_asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_serial_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;receiver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;baudrate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can connect a phone's bluetooth to a laptop bluetooth. From phone we can send messages to laptop using bluetooth terminal app like Serial bluetooth terminal&lt;sup id="fnref:asbt"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fn:asbt"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Here a screenshot of messages being send from an Android device.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/android-bluetooth.jpg" width="300" height="500" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;p&gt;We can listen to these messages on laptop via serial port by running the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;receiver.py&lt;span class="w"&gt; &lt;/span&gt;/dev/cu.Bluetooth-Incoming-Port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9600&lt;/span&gt;
&lt;span class="m"&gt;2020&lt;/span&gt;-08-31&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;:44:50.995281&lt;span class="w"&gt; &lt;/span&gt;Rx&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ping&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;android
&lt;span class="m"&gt;2020&lt;/span&gt;-08-31&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;:44:57.702866&lt;span class="w"&gt; &lt;/span&gt;Rx&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;message
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Bluetooth Sender&lt;/h4&gt;
&lt;p&gt;Now lets write a sender to send messages typed on the terminal to the bluetooth.&lt;/p&gt;
&lt;p&gt;To read input from terminal, we need to use aioconsole &lt;sup id="fnref:aioc"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fn:aioc"&gt;3&lt;/a&gt;&lt;/sup&gt;. It provides async input equivalent function to read input typed on the terminal.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;datetime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;dt&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;serial_asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;aioconsole&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;aioconsole&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_standard_streams&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; Tx ==&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;serial_asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open_serial_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;baudrate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can run the program with the following command and send messages to phone's bluetooth.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;sender.py&lt;span class="w"&gt; &lt;/span&gt;/dev/cu.Bluetooth-Incoming-Port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9600&lt;/span&gt;

ping&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;mac
&lt;span class="m"&gt;2020&lt;/span&gt;-08-31&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;:46:52.222676&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;ping&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;mac
&lt;span class="m"&gt;2020&lt;/span&gt;-08-31&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;:46:58.423492&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;message
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here a screenshot of messages received on Android device.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/android-bluetooth-receive.jpg" width="300" height="500" style="vertical-align:middle"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;If we combine the above two programmes, we get a simple bluetooth client to interact with any bluetooth via serial interface. Here is the complete code &lt;sup id="fnref:gist"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fn:gist"&gt;5&lt;/a&gt;&lt;/sup&gt; for the client.&lt;/p&gt;
&lt;p&gt;In the next article, lets see how to interact with Bluetooth LE devices.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:miniterm"&gt;
&lt;p&gt;&lt;a href="https://pyserial.readthedocs.io/en/latest/tools.html#module-serial.tools.miniterm"&gt;miniterm&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fnref:miniterm" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:pyserial-asyncio"&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/pyserial-asyncio/"&gt;pyserial-asyncio on PyPi&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fnref:pyserial-asyncio" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:aioc"&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/aioconsole/"&gt;aioconsole on PyPi&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fnref:aioc" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:asbt"&gt;
&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal"&gt;Serial Bluetooth Terminal on Play Store&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fnref:asbt" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:gist"&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/ChillarAnand/a7be6adeb84a63d48e8dda27aab7ac94"&gt;Python async client&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html#fnref:gist" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>bluetooth</category><category>featured</category><category>python</category><guid>https://avilpage.com/2020/08/bluetooth-terminal-python-asyncio.html</guid><pubDate>Mon, 31 Aug 2020 15:51:21 GMT</pubDate></item><item><title>Set Default Date For Date Hierarchy In Django Admin</title><link>https://avilpage.com/2020/07/default-date-hierarchy-in-django-admin.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When we monitor daily events from django admin, most of the time we are interested in events related to today. Django admin provides date based drill down navigation page via ModelAdmin.date_hierarchy&lt;sup id="fnref:dh"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/07/default-date-hierarchy-in-django-admin.html#fn:dh"&gt;1&lt;/a&gt;&lt;/sup&gt; option. With this, we can navigate to any date to filter out events related to that date.&lt;/p&gt;
&lt;p&gt;One problem with this drill down navigation is, we have to navigate to todays date every time we open a model in admin. Since we are interested in todays events most of the time, setting todays date as default filtered date will solve the problem.&lt;/p&gt;
&lt;h4&gt;Set Default Date For Date Hierarchy&lt;/h4&gt;
&lt;p&gt;Let us create an admin page to show all the users who logged in today. Since User model is already registered in admin by default, let us create a proxy model to register it again.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib.auth.models&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DjangoUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lets register this model in admin to show logged in users details along with date hierarchy.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;


&lt;span class="nd"&gt;@admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DjangoUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;MetaUserAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;list_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'is_active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'last_login'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;date_hierarchy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'last_login'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we open &lt;code&gt;DjangoUser&lt;/code&gt; model in admin page, it will show drill down navigation bar like this.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/django-admin-date.png"&gt;&lt;/p&gt;
&lt;p&gt;Now, if we drill down to a particular date, django adds additional query params to the admin url. For example, if we visit 2020-06-26 date, corresponding query params are &lt;code&gt;/?last_login__day=26&amp;amp;last_login__month=6&amp;amp;last_login__year=2020&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can override changelist view and set default params to todays date if there are no query params. If there are query params then render the original response.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;@admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DjangoUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MetaUserAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;list_display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'is_active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'last_login'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;date_hierarchy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'last_login'&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;changelist_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extra_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;GET&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;changelist_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extra_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;extra_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nc"&gt;date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nc"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;'day', 'month', 'year'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;field_keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;'{}__{}'.format(self.date_hierarchy, i) for i in params&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;field_values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;getattr(date, i) for i in params&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;query_params&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field_keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;field_values&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{}?{}'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_params&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now if we open the same admin page, it will redirect to todays date by default.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/django-admin-date2.png"&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how to set a default date for &lt;code&gt;date_hierarchy&lt;/code&gt; in admin page. We can also achieve similar filtering by settiing default values for &lt;code&gt;search_filter&lt;/code&gt; or &lt;code&gt;list_filter&lt;/code&gt; which will filter items related to any specific date.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:dh"&gt;
&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.date_hierarchy"&gt;Django docs - ModelAdmin.date_hierarchy&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/07/default-date-hierarchy-in-django-admin.html#fnref:dh" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>django</category><guid>https://avilpage.com/2020/07/default-date-hierarchy-in-django-admin.html</guid><pubDate>Fri, 31 Jul 2020 14:36:49 GMT</pubDate></item><item><title>How Dart, Flutter Stateful Hot Reload Work? - Part 1</title><link>https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;This will be a series of articles on exploring the internals of Dart &amp;amp; Flutter stateful hot reload. In the first article, lets write a simple dart program to see stateful hot reload in action. Then lets delve into details on what is happening.&lt;/p&gt;
&lt;h4&gt;Stateful Hot Reload&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'dart:async'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;adder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Total is &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="s2"&gt;. Adding &lt;/span&gt;&lt;span class="si"&gt;$&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periodic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;adder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above program&lt;sup id="fnref:program"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fn:program"&gt;1&lt;/a&gt;&lt;/sup&gt;, we are using a &lt;code&gt;Timer.periodic&lt;/code&gt;&lt;sup id="fnref:periodic"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fn:periodic"&gt;2&lt;/a&gt;&lt;/sup&gt; to create a timer which calls &lt;code&gt;adder&lt;/code&gt; function every 2 seconds.&lt;/p&gt;
&lt;p&gt;We can run this program from command line using&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;observe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hot_reload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dart&lt;/span&gt;
&lt;span class="n"&gt;Observatory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listening&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8181&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d42KmW4LknU&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will start executing the program and will provide a link to observatory&lt;sup id="fnref:observatory"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fn:observatory"&gt;3&lt;/a&gt;&lt;/sup&gt;, a tool to profile/debug Dart applications.&lt;/p&gt;
&lt;p&gt;As the program is executing, lets open the program in an editor, change delta from 2 to 3.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we restart the program, it will start executing from the beginning and it will lose the state of the program.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;observe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hot_reload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dart&lt;/span&gt;
&lt;span class="n"&gt;Observatory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listening&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8181&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;eoP2lpC2ZWw&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;9.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of restart, we can open the observatory link in browser, open main isolate and click on &lt;code&gt;Reload Source&lt;/code&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/dart-vm.png"&gt;&lt;/p&gt;
&lt;p&gt;As we can see from the below output, it did a stateful hot reload and state of the program is preserved instead of starting from the beginning.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;observe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hot_reload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dart&lt;/span&gt;
&lt;span class="n"&gt;Observatory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listening&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8181&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n_GSAKsyr5s&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;11.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# after hot reload&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;14.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;17.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;20.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;During a hot reload, Dart VM will apply changes to a live program&lt;sup id="fnref:hot"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fn:hot"&gt;4&lt;/a&gt;&lt;/sup&gt;. If the source code of a method is changed, VM will replace the methods with the new updated methods. Next time, when the program looks up for a particular method, it will find the updated method and use it.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how hot reload works by writing a simple program in Dart. In the upcoming articles, lets dive into the Dart VM internals, Flutter architecture and other nitty gritties of hot reload.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:program"&gt;
&lt;p&gt;&lt;a href="https://www.reddit.com/r/FlutterDev/comments/f7sn1w/how_stateful_hot_reloading_of_flutter_works_under/fij638y/"&gt;https://www.reddit.com/r/FlutterDev/hot-reload&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fnref:program" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:periodic"&gt;
&lt;p&gt;&lt;a href="https://api.dart.dev/stable/2.8.4/dart-async/Timer/Timer.periodic.html"&gt;dart.dev/dart-async/Timer/Timer.periodic.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fnref:periodic" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:observatory"&gt;
&lt;p&gt;&lt;a href="https://dart.dev/tools/dart-observatory"&gt;https://dart.dev/tools/dart-observatory&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fnref:observatory" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:hot"&gt;
&lt;p&gt;&lt;a href="https://github.com/dart-lang/sdk/wiki/Hot-reload"&gt;https://github.com/dart-lang/sdk/wiki/Hot-reload&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html#fnref:hot" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>dart</category><category>featured</category><guid>https://avilpage.com/2020/06/how-dart-flutter-hot-reload-work-part-1.html</guid><pubDate>Tue, 30 Jun 2020 13:47:20 GMT</pubDate></item><item><title>Tips On Improving kubectl Productivity</title><link>https://avilpage.com/2020/05/tips-on-improving-kubectl-productivity.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;code&gt;kubectl&lt;/code&gt; is CLI tool to control Kubernetes clusters. As we start using kubectl to interact with mutliple clusters, we end up running lengthy commands and even running multiple commands for simple tasks like running a shell in a container.&lt;/p&gt;
&lt;p&gt;In this article, lets learn few tips to improve our productivity when using kubectl.&lt;/p&gt;
&lt;h4&gt;Aliases&lt;/h4&gt;
&lt;p&gt;Aliases in general improve the productivity when using a shell.&lt;/p&gt;
&lt;p&gt;kubectl provides shortcuts for commands. For example,&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# instead of running full command&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;services

&lt;span class="c1"&gt;# we can use short hand version&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;svc
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It also provides completion for commands.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# enable completion for zsh&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;completion&lt;span class="w"&gt; &lt;/span&gt;zsh&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# type `kubectl ` and hit `&amp;lt;TAB&amp;gt;` will show possible options&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;kubectl
annotate&lt;span class="w"&gt;       &lt;/span&gt;attach&lt;span class="w"&gt;         &lt;/span&gt;cluster-info
api-resources&lt;span class="w"&gt;  &lt;/span&gt;auth&lt;span class="w"&gt;           &lt;/span&gt;completion
api-versions&lt;span class="w"&gt;   &lt;/span&gt;autoscale&lt;span class="w"&gt;      &lt;/span&gt;config
apply&lt;span class="w"&gt;          &lt;/span&gt;certificate&lt;span class="w"&gt;    &lt;/span&gt;convert

&lt;span class="c1"&gt;# type `kubectl g`, and hit `&amp;lt;TAB&amp;gt;` will show possible options&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Even though completions are helpful, setting up up aliases for most commanly used commands will save a lot of time.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kdp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl describe pod'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kgp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl get pods'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kgpa&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl get pods --all-namespaces'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl exec -it'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;wkgp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'watch -n1 kubectl getp pods'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kga&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl get all'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kgaa&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl get all --all-namespaces'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kaf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl apply -f'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kcgc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl config get-contexts'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;kccc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl config current-context'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you don't write your own aliases, there is &lt;a href="https://github.com/ahmetb/kubectl-aliases"&gt;kubectl-aliases&lt;/a&gt; which provides exhuastive list of aliases. We can source this file in rc file and start using them.&lt;/p&gt;
&lt;h4&gt;Use Functions&lt;/h4&gt;
&lt;p&gt;Even though aliases help us to run lengthy commands with an alias, there are times where we have to run multiple commands to get things done for a single task.&lt;/p&gt;
&lt;p&gt;For example, to view kubenetes dashboard, we have to get the token, start proxy server and then open the url in browser. We can write a simple function as shown below to do all of that.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;kp&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;kubernetes-dashboard&lt;span class="w"&gt; &lt;/span&gt;describe&lt;span class="w"&gt; &lt;/span&gt;secret&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;kubernetes-dashboard&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;secret&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;admin-user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{print $1}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'token:'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{print $2}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pbcopy
&lt;span class="w"&gt;    &lt;/span&gt;open&lt;span class="w"&gt; &lt;/span&gt;http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
&lt;span class="w"&gt;    &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;proxy
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now from the shell, when we run &lt;code&gt;kp&lt;/code&gt;, it function will copy the token to clipboard, open kubernetes dashboard in browser and will start the proxy server.&lt;/p&gt;
&lt;h4&gt;Use Labels&lt;/h4&gt;
&lt;p&gt;To describe a pod or tail logs from a pod, we can use pod names.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pods
NAME&lt;span class="w"&gt;                             &lt;/span&gt;READY&lt;span class="w"&gt;   &lt;/span&gt;STATUS
hello-world-79d794c659-tpfv2&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;/1&lt;span class="w"&gt;     &lt;/span&gt;Running


$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;describe&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt; &lt;/span&gt;hello-world-79d794c659-tpfv2

$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;pod/hello-world-79d794c659-tpfv2
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the app gets updated, the name of pod also updates. If your shell has auto completion feature, it will autocomplete to previous name.&lt;/p&gt;
&lt;p&gt;So, instead of using pod name, we can use pod labels as mentioned below.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;describe&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="o"&gt;=&lt;/span&gt;hello-world

$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="o"&gt;=&lt;/span&gt;pod/hello-world
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We run the command once and next time shell will show autocomplete and we can use that directly.&lt;/p&gt;
&lt;h4&gt;Kubectl Tools&lt;/h4&gt;
&lt;p&gt;k8s has a good ecosystem and the following packages are aimed to make certain k8s tasks easier.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/aylei/kubectl-debug"&gt;kubectl-debug&lt;/a&gt; - Debug pod by a new container with all troubleshooting tools pre-installed.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pixel-point/kube-forwarder"&gt;kube-forwarder&lt;/a&gt; - Easy to use port forwarding manager.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/wercker/stern"&gt;stern&lt;/a&gt; - Multi pod and container log tailing.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ahmetb/kubectx"&gt;kubectx&lt;/a&gt; - Quick way to switch between clusters and namespaces.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/astefanutti/kubebox"&gt;kubebox&lt;/a&gt; - Terminal and Web console for Kubernetes.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/derailed/k9s"&gt;k9s&lt;/a&gt; - Interactive terminal UI.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/IBM/kui"&gt;kui&lt;/a&gt; - Hybrid CLI/UI tool for k8s.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/databricks/click"&gt;click&lt;/a&gt; - Interactive controller for k8s.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/lensapp/lens"&gt;lens&lt;/a&gt; - Stand alone corss platform k8s IDE.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article we have seen some useful methods as well as some tools to improve productivity with kubectl. If you spend a lot of time interacting with kubernetes cluster, it is important to notice your workflows and find better tools or ways to improve productivity.&lt;/p&gt;</description><category>devops</category><category>kubernetes</category><guid>https://avilpage.com/2020/05/tips-on-improving-kubectl-productivity.html</guid><pubDate>Sun, 31 May 2020 13:12:00 GMT</pubDate></item><item><title>Continuous Deployment To Kubernetes With Skaffold</title><link>https://avilpage.com/2020/04/setup-continuous-deployment-with-kubernetes.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;In this article, let us see how to set up a continuous deployment pipeline to Kubernetes in CircleCI using Skaffold.&lt;/p&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;You should have a kubernetes cluster in a cloud environment or in your local machine. Check your cluster status with the following commands.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;cluster-info
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;get-contexts
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should know how to manually deploy your application to kubernetes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# push latest docker image to container registry&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;chillaranand/library

&lt;span class="c1"&gt;# deploy latest image to k8s&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;app/deployment.yaml
$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;apply&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;app/service.yaml
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Skaffold&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/GoogleContainerTools/skaffold"&gt;Skaffold&lt;/a&gt; is a CLI tool to facilitate continuous development and deployment workflows for Kubernetes applications.&lt;/p&gt;
&lt;p&gt;Skaffold binaries are available for all platforms. Download the binary file for your OS and move it to bin folder.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-Lo&lt;span class="w"&gt; &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;https://storage.googleapis.com/skaffold/releases/latest/skaffold-darwin-amd64
$&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;skaffold
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside your project root, run &lt;code&gt;init&lt;/code&gt; command to generate a config file. If your project has k8s manifests, it will detect them and include it in the configuration file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;init
Configuration&lt;span class="w"&gt; &lt;/span&gt;skaffold.yaml&lt;span class="w"&gt; &lt;/span&gt;was&lt;span class="w"&gt; &lt;/span&gt;written

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;skaffold.yaml
apiVersion:&lt;span class="w"&gt; &lt;/span&gt;skaffold/v2beta1
kind:&lt;span class="w"&gt; &lt;/span&gt;Config
metadata:
&lt;span class="w"&gt;  &lt;/span&gt;name:&lt;span class="w"&gt; &lt;/span&gt;library
build:
&lt;span class="w"&gt;  &lt;/span&gt;artifacts:
&lt;span class="w"&gt;  &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;image:&lt;span class="w"&gt; &lt;/span&gt;docker.io/chillaranand/library
deploy:
&lt;span class="w"&gt;  &lt;/span&gt;kubectl:
&lt;span class="w"&gt;    &lt;/span&gt;manifests:
&lt;span class="w"&gt;    &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;kubernetes/deployment.yaml
&lt;span class="w"&gt;    &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;kubernetes/service.yaml
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To deploy latest changes to your cluster, run&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;run
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will build the docker image, push to registry and will apply the manifests in the clusters. Now, k8s will pull the latest image from the registry and create a new deployment.&lt;/p&gt;
&lt;h4&gt;CircleCI Workflow&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;version:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.1

orbs:
&lt;span class="w"&gt;  &lt;/span&gt;aws-cli:&lt;span class="w"&gt; &lt;/span&gt;circleci/aws-cli@0.1.19
&lt;span class="w"&gt;  &lt;/span&gt;kubernetes:&lt;span class="w"&gt; &lt;/span&gt;circleci/kubernetes@0.11.0

commands:
&lt;span class="w"&gt;  &lt;/span&gt;kubernetes-deploy:

&lt;span class="w"&gt;    &lt;/span&gt;steps:
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;setup_remote_docker

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;aws-cli/setup:
&lt;span class="w"&gt;          &lt;/span&gt;profile-name:&lt;span class="w"&gt; &lt;/span&gt;default

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;kubernetes/install-kubectl:
&lt;span class="w"&gt;          &lt;/span&gt;kubectl-version:&lt;span class="w"&gt; &lt;/span&gt;v1.15.10

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;checkout

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;run:
&lt;span class="w"&gt;          &lt;/span&gt;name:&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;registry&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;command:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;aws&lt;span class="w"&gt; &lt;/span&gt;ecr&lt;span class="w"&gt; &lt;/span&gt;get-login&lt;span class="w"&gt; &lt;/span&gt;--region&lt;span class="w"&gt; &lt;/span&gt;ap-south-1&lt;span class="w"&gt; &lt;/span&gt;--no-include-email&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;run:
&lt;span class="w"&gt;          &lt;/span&gt;name:&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;skaffold
&lt;span class="w"&gt;          &lt;/span&gt;command:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-Lo&lt;span class="w"&gt; &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
&lt;span class="w"&gt;            &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;skaffold
&lt;span class="w"&gt;            &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;run:
&lt;span class="w"&gt;          &lt;/span&gt;name:&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;kube&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;connect&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;required&lt;span class="w"&gt; &lt;/span&gt;cluster
&lt;span class="w"&gt;          &lt;/span&gt;command:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;aws&lt;span class="w"&gt; &lt;/span&gt;eks&lt;span class="w"&gt; &lt;/span&gt;--region&lt;span class="w"&gt; &lt;/span&gt;ap-south-1&lt;span class="w"&gt; &lt;/span&gt;update-kubeconfig&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;demo-cluster

&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;run:
&lt;span class="w"&gt;          &lt;/span&gt;name:&lt;span class="w"&gt; &lt;/span&gt;deploy&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;k8s
&lt;span class="w"&gt;          &lt;/span&gt;command:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;skaffold&lt;span class="w"&gt; &lt;/span&gt;run
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;CircleCI orbs are shareable packages to speed up CI setup. Here we are using aws-cli, kubernetes orbs to easily install/setup them inside the CI environment.&lt;/p&gt;
&lt;p&gt;Since CircleCI builds run in a docker container, to run docker commands inside container, we have to specify &lt;code&gt;setup_remote_docker&lt;/code&gt; key so that a separate environment is created for it.&lt;/p&gt;
&lt;p&gt;Remaining steps are self explainatory.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Here we have seen how to set up CD to kubernetes in CircleCI. If we want to set up this another CI like Jenkins or Travis, instead of using orbs, we have to use system package mangers like apt-get to install them. All others steps will remain same.&lt;/p&gt;</description><category>aws</category><category>devops</category><category>kubernetes</category><guid>https://avilpage.com/2020/04/setup-continuous-deployment-with-kubernetes.html</guid><pubDate>Thu, 30 Apr 2020 11:15:36 GMT</pubDate></item><item><title>Work From Home Tips For Non-remote Workers</title><link>https://avilpage.com/2020/04/work-from-home-tips.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Remote-first and remote-friendly companies have a different work culture &amp;amp; communication process compared to non-remote companies. Due to COVID-19&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/04/work-from-home-tips.html#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; world wide pandemic, majority of workers who didn't had prior remote experience are WFH(working from home). This article is intended to provide some helpful tips for such people.&lt;/p&gt;
&lt;h4&gt;Work Desk&lt;/h4&gt;
&lt;p&gt;It is important to have a dedicated room or at least a desk for work. This creates a virtual boundary between your office work and personal work. Otherwise, you will end up working from bed, dining tables, kitchen etc which will result in body pains due to bad postures.&lt;/p&gt;
&lt;h4&gt;Get Ready&lt;/h4&gt;
&lt;p align="center"&gt;

Image Credit:
&lt;cite&gt;raywenderlich
&lt;sup id="fnref-2"&gt;
&lt;a class="footnote-ref" href="https://avilpage.com/2020/04/work-from-home-tips.html#fn-1"&gt;2&lt;/a&gt;
&lt;/sup&gt;
&lt;/cite&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remote-work.png"&gt;
&lt;/p&gt;

&lt;p&gt;Start your daily routine as if you are going to office. It is easy to stop caring about personal grooming and attire when WFH. Your attire can influence your focus and productivity.&lt;/p&gt;
&lt;p&gt;If you find getting ready is hard, schedule video calls for all meetings with your colleagues. This might give some additional motivation for you to get ready early in the morning. When the work time, go to your work desk and start working.&lt;/p&gt;
&lt;h4&gt;Self Discipline&lt;/h4&gt;
&lt;p&gt;Schedule your work time. Whenever possible try to stick to office working hours. Without proper schedule, you will either end up under working or over working as your personal work and office work gets mixed up.&lt;/p&gt;
&lt;p&gt;Take regular breaks during work hours. Without any distractions, it is easy to get lost in the pixels for longer durations. Taking short breaks for a quick walk and getting a fresh air outside will freshen up.&lt;/p&gt;
&lt;p&gt;With unlimited access to kitchen and snacks, it is hard to avoid binge eating at home. But atleast avoid binge eating during office hours.&lt;/p&gt;
&lt;p&gt;Exercise. Since WFH involves only sitting in a chair through out the day, staying physically active is challenging especially during this pandemic. Exercise few minutes every morning, help yourself in the kitchen by making a meal or doing dishes, clean your house etc., should help in staying physically active.&lt;/p&gt;
&lt;h4&gt;Seek Help&lt;/h4&gt;
&lt;p&gt;WFH can be lonely at times as the social interactions are quite less. Schedule 1 to 1 meetings or virtual coffe meetings with your colleagues to increase social interactions. Discuss WFH problems with your colleagues, friends and remote communities to see how they are tacking those problems.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Coronavirus_disease_2019"&gt;https://en.wikipedia.org/wiki/Coronavirus_disease_2019&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/04/work-from-home-tips.html#fnref:1" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a href="https://www.raywenderlich.com/9573880-staying-motivated-as-a-work-from-home-developer"&gt;https://www.raywenderlich.com/9573880-staying-motivated-as-a-work-from-home-developer&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/04/work-from-home-tips.html#fnref:2" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>careers</category><guid>https://avilpage.com/2020/04/work-from-home-tips.html</guid><pubDate>Tue, 31 Mar 2020 13:09:58 GMT</pubDate></item><item><title>How To Reduce Python Package Footprint?</title><link>https://avilpage.com/2020/02/reduce-python-package-footprint.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;PyPi&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; hosts over 210K+ projects and the average size of Python package is less than 1MB. However some of the most used packages in scientific computing like NumPy, SciPy has large footprint as they bundle shared libraries&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt; along with the package.&lt;/p&gt;
&lt;h4&gt;Build From Source&lt;/h4&gt;
&lt;p&gt;If a project needs to be deployed in AWS Lambda, the total size of deployment package should be less than 250MB&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;numpy

$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-hs&lt;span class="w"&gt; &lt;/span&gt;~/.virtualenvs/py37/lib/python3.7/site-packages/numpy/
&lt;span class="w"&gt; &lt;/span&gt;85M&lt;span class="w"&gt;    &lt;/span&gt;/Users/avilpage/.virtualenvs/all3/lib/python3.7/site-packages/numpy/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just numpy occupies 85MB space on Mac machine. If we include a couple of other packages like scipy &amp;amp; pandas, overall size of the package crosses 250MB.&lt;/p&gt;
&lt;p&gt;An easy way reduce the size of python packages is to build from source instead of use pre-compiled wheels.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CLFAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'-g0 -Wl -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;numpy&lt;span class="w"&gt; &lt;/span&gt;--global-option&lt;span class="o"&gt;=&lt;/span&gt;build_ext

$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-hs&lt;span class="w"&gt; &lt;/span&gt;~/.virtualenvs/py37/lib/python3.7/site-packages/numpy/
&lt;span class="w"&gt; &lt;/span&gt;23M&lt;span class="w"&gt;    &lt;/span&gt;/Users/avilpage/.virtualenvs/all3/lib/python3.7/site-packages/numpy/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can see the footprint has reduced by ~70% when using sdist instead of wheel. This&lt;sup id="fnref:4"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fn:4"&gt;4&lt;/a&gt;&lt;/sup&gt; article provides more details about these CFLAG optimization when installing a package from source.&lt;/p&gt;
&lt;h4&gt;Shared Packages&lt;/h4&gt;
&lt;p&gt;When using a laptop with low storage for multiple projects with conflicting dependencies, a seperate virtual environment is needed for each project. This will lead to installing same version of the package in multiple places which increases the footprint.&lt;/p&gt;
&lt;p&gt;To avoid this, we can create a shared virtual environment which has most commonly used packages and share it across all the enviroments. For example, we can create a shared virtual enviroment with all the packages required for scientific computing.&lt;/p&gt;
&lt;p&gt;For each project, we can create a virtual enviroment and share all packages of the common enviroment. If any project requires a specific version of the package, the same package can be install in project enviroment.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;common-requirements.txt&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# shared across all enviroments&lt;/span&gt;
&lt;span class="nv"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.18.1
&lt;span class="nv"&gt;pandas&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.0.1
&lt;span class="nv"&gt;scipy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.4.1

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;project1-requirements.txt&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# project1 requirements&lt;/span&gt;
&lt;span class="nv"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.18.1
&lt;span class="nv"&gt;pandas&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.0.0
&lt;span class="nv"&gt;scipy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.4.1

$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;project2-requirements.txt&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# project2 enviroments&lt;/span&gt;
&lt;span class="nv"&gt;numpy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.17
&lt;span class="nv"&gt;pandas&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.0.0
&lt;span class="nv"&gt;scipy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.4.1
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After creating a virtual enviroment for a project, we can create a &lt;code&gt;.pth&lt;/code&gt; file with the path of site-packages of common virtual enviroment so that all those packages are readily available in the new project.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/users/avilpage/.virtualenvs/common/lib/python3.7/site-packages'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;
&lt;span class="w"&gt; &lt;/span&gt;~/.virtualenvs/project1/lib/python3.7/site-packages/common.pth
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then we can install the project requirements which will install only missing packages.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;project1-requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Global Store&lt;/h4&gt;
&lt;p&gt;The above shared packages solution has couple issues.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User has to manually create and track shared packages for each Python version and needs to bootstrap it in every project.&lt;/li&gt;
&lt;li&gt;When there is an incompatible version of package in multiple projects, user will end up with duplicate installations of the same version.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To solve this&lt;sup id="fnref:5"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fn:5"&gt;5&lt;/a&gt;&lt;/sup&gt;, we can have a global store of packages in a single location segregated by python and package version. Whenever a user tries to install a package, check if the package is in global store. If not install it in global store. If present, just link the package to virtualenvs.&lt;/p&gt;
&lt;p&gt;For example, numpy1.17 for Python 3.7 and numpy1.18 for Python 3.6 can be stored in the global store as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python3.6&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--target&lt;span class="w"&gt; &lt;/span&gt;~/.mpip/numpy/3.6_1.18&lt;span class="w"&gt; &lt;/span&gt;numpy

$&lt;span class="w"&gt; &lt;/span&gt;python3.7&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--target&lt;span class="w"&gt; &lt;/span&gt;~/.mpip/numpy/3.7_1.17&lt;span class="w"&gt; &lt;/span&gt;numpy

&lt;span class="c1"&gt;# in project venv&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'~/.mpip/numpy/3.7_1.17'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;PATH_TO_ENV/lib/python3.7/site-packages/numpy.pth
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this, we can ensure one version of the package is stored in the disk only once. I have created a simple package manager called mpip&lt;sup id="fnref:6"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fn:6"&gt;6&lt;/a&gt;&lt;/sup&gt; as a POC to test this and it seems to work as expected.&lt;/p&gt;
&lt;p&gt;These are couple of ways to reduce to footprint of Python packages in a single environment as well as muliple enviroments.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://pypi.org/"&gt;https://pypi.org/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fnref:1" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a href="https://github.com/numpy/numpy/issues/10920"&gt;https://github.com/numpy/numpy/issues/10920&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fnref:2" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html"&gt;https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fnref:3" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a href="https://towardsdatascience.com/how-to-shrink-numpy-scipy-pandas-and-matplotlib-for-your-data-product-4ec8d7e86ee4"&gt;https://towardsdatascience.com/how-to-shrink-numpy-scipy-pandas-and-matplotlib-for-your-data-product-4ec8d7e86ee4&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fnref:4" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;a href="https://github.com/pypa/packaging-problems/issues/328"&gt;https://github.com/pypa/packaging-problems/issues/328&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fnref:5" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;&lt;a href="https://github.com/ChillarAnand/mpip"&gt;https://github.com/ChillarAnand/mpip&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2020/02/reduce-python-package-footprint.html#fnref:6" title="Jump back to footnote 6 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>aws</category><category>featured</category><category>python</category><guid>https://avilpage.com/2020/02/reduce-python-package-footprint.html</guid><pubDate>Sat, 29 Feb 2020 14:50:38 GMT</pubDate></item><item><title>Disabling Atomic Transactions In Django Test Cases</title><link>https://avilpage.com/2020/01/disable-transactions-django-tests.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/dev/topics/testing/tools/#testcase"&gt;TestCase&lt;/a&gt; is the most used class for writing tests in Django. To make tests faster, it wraps all the tests in 2 nested &lt;code&gt;atomic&lt;/code&gt; blocks.&lt;/p&gt;
&lt;p&gt;In this article, we will see where these atomic blocks create problems and find ways to disable it.&lt;/p&gt;
&lt;h4&gt;Select for update&lt;/h4&gt;
&lt;p&gt;Django provides &lt;a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#select-for-update"&gt;select_for_update()&lt;/a&gt; method on model managers which returns a queryset that will lock rows till the end of transaction.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;update_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select_for_update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When writing test case for a piece of code that uses &lt;code&gt;select_for_update&lt;/code&gt;, Django recomends not to use TestCase as it might not raise &lt;code&gt;TransactionManagementError&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Threads&lt;/h4&gt;
&lt;p&gt;Let us take a view which uses threads to get data from database.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get_books&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;serializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BookSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queryset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;many&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;BookViewSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ViewSet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A test which writes some data to db and then calls this API will fail to fetch the data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;LibraryPaidUserTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_get_books&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test book'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'books-list'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Threads in the view create a new connection to the database and they don't see the created test data as the transaction is not yet commited.&lt;/p&gt;
&lt;h4&gt;Transaction Test Case&lt;/h4&gt;
&lt;p&gt;To handle above 2 scenarios or other scenarios where database transaction behaviour needs to be tested, Django recommends to use &lt;code&gt;TransactionTestCase&lt;/code&gt; instead of TestCase.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TransactionTestCase&lt;/span&gt;

&lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;LibraryPaidUserTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TransactionTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_get_books&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With TransactionTestCase, db will be in auto commit mode and threads will be able to fetch the data commited earlier.&lt;/p&gt;
&lt;p&gt;Consider a scenario, where there are other utility classes which are subclassed from TestCase.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;LibraryTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;LibraryUserTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LibraryTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;LibraryPaidUserTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LibraryTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we subclass LibraryTestCase with TransactionTestCase, it will slow down the entire test suite as all the tests run in autocommit mode.&lt;/p&gt;
&lt;p&gt;If we subclass LibraryUserTestCase with TransactionTestCase, we will miss the functionality in LibraryTestCase. To prevent this, we can override the custom methods to call TransactionTestCase.&lt;/p&gt;
&lt;p&gt;If we look at the source code of TestCase, it has 4 methods to handle atomic transactions. We can override them to prevent creation of atomic transactions.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;LibraryPaidUserTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LibraryTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;setUpClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setUpClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;tearDownClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tearDownClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;_fixture_setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_fixture_setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;_fixture_teardown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_fixture_teardown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also create a mixin with the above methods and subclass it wherever this functionality is needed.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Django wraps tests in TestCase inside atomic transactions to speed up the run time. When we are testing for db transaction behaviours, we have to disable this using appropriate methods.&lt;/p&gt;</description><category>django</category><category>python</category><guid>https://avilpage.com/2020/01/disable-transactions-django-tests.html</guid><pubDate>Fri, 31 Jan 2020 15:51:21 GMT</pubDate></item><item><title>Mastering DICOM - #1 Clinical Workflows 101</title><link>https://avilpage.com/2019/12/mastering-dicom-part-1.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In hospitals, &lt;a href="https://en.wikipedia.org/wiki/Picture_archiving_and_communication_system"&gt;PACS&lt;/a&gt; simplifies the clinical workflow by reducing physical and time barriers. A typical radiology workflow looks like this.&lt;/p&gt;
&lt;p algin="center"&gt;
&lt;img src="https://avilpage.com/images/dicom-pacs-python1.png"&gt;
&lt;/p&gt;

&lt;p&gt;Credit: &lt;cite&gt;Wikipedia&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;A patient as per doctor's request will visit a radiology center to undergo CT/MRI/X-RAY. Data captured from modality(medical imaging equipments like CT/MRI machine) will be sent to QA for verfication and then sent to PACS for archiving.&lt;/p&gt;
&lt;p&gt;After this when patient visits doctor, doctor can see this study on his workstation(which has DICOM viewer) by entering patient details.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://avilpage.com/tags/dicom.html"&gt;this series of articles&lt;/a&gt;, we will how to achieve this seamless transfer of medical data digitally with DICOM.&lt;/p&gt;
&lt;h4&gt;DICOM standard&lt;/h4&gt;
&lt;p&gt;DICOM modalities create files in DICOM format. This file has dicom header which contains meta data and dicom data set which has modality info(equipment information, equipment configuration etc), patient information(name, sex etc) and the image data.&lt;/p&gt;
&lt;p&gt;Storing and retreiving DICOM files from PACS servers is generally achieved through DIMSE DICOM for desktop applications and DICOMWeb for web applications.&lt;/p&gt;
&lt;p&gt;All the machines which transfer/receive DICOM data must follow DICOM standard. With this all the DICOM machines which are in a network can store and retrieve DICOM files from PACS.&lt;/p&gt;
&lt;p&gt;When writing software to handle DICOM data, there are third party packages to handle most of the these things for us.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Python(&lt;a href="https://pypi.org/project/pydicom/"&gt;pydicom&lt;/a&gt;, &lt;a href="https://pypi.org/project/pynetdicom/"&gt;pynetdicom&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ruby (&lt;a href="https://rubygems.org/gems/dicom/"&gt;ruby-dicom&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;R (&lt;a href="https://CRAN.R-project.org/package=oro.dicom"&gt;oro.dicom&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C/C++ (&lt;a href="https://dicom.offis.de/dcmtk"&gt;dcmtoolkit&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have learnt the clinical radiology workflow and how DICOM standard is useful in digitally transferring data between DICOM modalities.&lt;/p&gt;
&lt;p&gt;In the next article, we will dig into DICOM file formats and learn about the structure of DICOM data.&lt;/p&gt;</description><category>dicom</category><category>HealthIT</category><category>python</category><guid>https://avilpage.com/2019/12/mastering-dicom-part-1.html</guid><pubDate>Tue, 31 Dec 2019 13:29:09 GMT</pubDate></item><item><title>Verifying TLS Certificate Chain With OpenSSL</title><link>https://avilpage.com/2019/11/verify-tls-certificate-chain-with-openssl.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;To communicate securely over the internet, HTTPS (HTTP over TLS) is used. A key component of HTTPS is Certificate authority (CA), which by issuing digital certificates acts as a trusted 3rd party between server(eg: google.com) and others(eg: mobiles, laptops).&lt;/p&gt;
&lt;p&gt;In this article, we will learn how to obtain certificates from a server and manually verify them on a laptop to establish a chain of trust.&lt;/p&gt;
&lt;h4&gt;Chain of Trust&lt;/h4&gt;
&lt;p&gt;TLS certificate chain typically consists of server certificate which is signed by intermediate certificate of CA which is inturn signed with CA root certificate.&lt;/p&gt;
&lt;p&gt;Using OpenSSL, we can gather the server and intermediate certificates sent by a server using the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;s_client&lt;span class="w"&gt; &lt;/span&gt;-showcerts&lt;span class="w"&gt; &lt;/span&gt;-connect&lt;span class="w"&gt; &lt;/span&gt;avilpage.com:443

CONNECTED&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;00000006&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;US,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;Inc,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;www.digicert.com,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;EV&lt;span class="w"&gt; &lt;/span&gt;Root&lt;span class="w"&gt; &lt;/span&gt;CA
verify&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;:1
&lt;span class="nv"&gt;depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;US,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;Inc,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;www.digicert.com,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;SHA2&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;Server&lt;span class="w"&gt; &lt;/span&gt;CA
verify&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;:1
&lt;span class="nv"&gt;depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;US,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;California,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;San&lt;span class="w"&gt; &lt;/span&gt;Francisco,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GitHub, Inc."&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;www.github.com
verify&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;:1
---
Certificate&lt;span class="w"&gt; &lt;/span&gt;chain
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;s:/C&lt;span class="o"&gt;=&lt;/span&gt;US/ST&lt;span class="o"&gt;=&lt;/span&gt;California/L&lt;span class="o"&gt;=&lt;/span&gt;San&lt;span class="w"&gt; &lt;/span&gt;Francisco/O&lt;span class="o"&gt;=&lt;/span&gt;GitHub,&lt;span class="w"&gt; &lt;/span&gt;Inc./CN&lt;span class="o"&gt;=&lt;/span&gt;www.github.com
&lt;span class="w"&gt;   &lt;/span&gt;i:/C&lt;span class="o"&gt;=&lt;/span&gt;US/O&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;Inc/OU&lt;span class="o"&gt;=&lt;/span&gt;www.digicert.com/CN&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;SHA2&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;Server&lt;span class="w"&gt; &lt;/span&gt;CA
-----BEGIN&lt;span class="w"&gt; &lt;/span&gt;CERTIFICATE-----
MIIHMTCCBhmgAwIBAgIQDf56dauo4GsS0tOc8
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlna
0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvF
aTrrJ67dru040my
-----END&lt;span class="w"&gt; &lt;/span&gt;CERTIFICATE-----
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;s:/C&lt;span class="o"&gt;=&lt;/span&gt;US/O&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;Inc/OU&lt;span class="o"&gt;=&lt;/span&gt;www.digicert.com/CN&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;SHA2&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;Server&lt;span class="w"&gt; &lt;/span&gt;CA
&lt;span class="w"&gt;   &lt;/span&gt;i:/C&lt;span class="o"&gt;=&lt;/span&gt;US/O&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;Inc/OU&lt;span class="o"&gt;=&lt;/span&gt;www.digicert.com/CN&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;EV&lt;span class="w"&gt; &lt;/span&gt;Root&lt;span class="w"&gt; &lt;/span&gt;CA
-----BEGIN&lt;span class="w"&gt; &lt;/span&gt;CERTIFICATE-----
MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtC
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln
0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHv
&lt;span class="nv"&gt;cPUeybQ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
-----END&lt;span class="w"&gt; &lt;/span&gt;CERTIFICATE-----

&lt;span class="w"&gt;    &lt;/span&gt;Verify&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;code:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ok&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command internally verfies if the certificate chain is valid. The output contains the server certificate and the intermediate certificate along with their issuer and subject. Copy both the certificates into &lt;code&gt;server.pem&lt;/code&gt; and &lt;code&gt;intermediate.pem&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;We can decode these pem files and see the information in these certificates using&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;x509&lt;span class="w"&gt; &lt;/span&gt;-noout&lt;span class="w"&gt; &lt;/span&gt;-text&lt;span class="w"&gt; &lt;/span&gt;-in&lt;span class="w"&gt; &lt;/span&gt;server.crt

Certificate:
&lt;span class="w"&gt;    &lt;/span&gt;Data:
&lt;span class="w"&gt;        &lt;/span&gt;Version:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;0x2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Signature&lt;span class="w"&gt; &lt;/span&gt;Algorithm:&lt;span class="w"&gt; &lt;/span&gt;sha256WithRSAEncryption
&lt;span class="w"&gt;    &lt;/span&gt;----
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also get only the subject and issuer of the certificate with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;x509&lt;span class="w"&gt; &lt;/span&gt;-noout&lt;span class="w"&gt; &lt;/span&gt;-subject&lt;span class="w"&gt; &lt;/span&gt;-noout&lt;span class="w"&gt; &lt;/span&gt;-issuer&lt;span class="w"&gt; &lt;/span&gt;-in&lt;span class="w"&gt; &lt;/span&gt;server.pem

&lt;span class="nv"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;www.github.com
&lt;span class="nv"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;SHA2&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;Server&lt;span class="w"&gt; &lt;/span&gt;CA

$&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;x509&lt;span class="w"&gt; &lt;/span&gt;-noout&lt;span class="w"&gt; &lt;/span&gt;-subject&lt;span class="w"&gt; &lt;/span&gt;-noout&lt;span class="w"&gt; &lt;/span&gt;-issuer&lt;span class="w"&gt; &lt;/span&gt;-in&lt;span class="w"&gt; &lt;/span&gt;intermediate.pem

&lt;span class="nv"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;SHA2&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;Server&lt;span class="w"&gt; &lt;/span&gt;CA
&lt;span class="nv"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DigiCert&lt;span class="w"&gt; &lt;/span&gt;High&lt;span class="w"&gt; &lt;/span&gt;Assurance&lt;span class="w"&gt; &lt;/span&gt;EV&lt;span class="w"&gt; &lt;/span&gt;Root&lt;span class="w"&gt; &lt;/span&gt;CA
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that we have both server and intermediate certificates at hand, we need to look for the relevant root certificate (in this case DigiCert High Assurance EV Root CA) in our system to verify these.&lt;/p&gt;
&lt;p&gt;If you are using a Linux machine, all the root certificate will readily available in &lt;code&gt;.pem&lt;/code&gt; format in &lt;code&gt;/etc/ssl/certs&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;If you are using a Mac, open &lt;code&gt;Keychain Access&lt;/code&gt;, search and export the relevant root certificate in &lt;code&gt;.pem&lt;/code&gt; format.&lt;/p&gt;
&lt;p algin="center"&gt;
&lt;img src="https://avilpage.com/images/tls-openssl1.png"&gt;
&lt;/p&gt;

&lt;p&gt;We have all the 3 certificates in the chain of trust and we can validate them with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;verify&lt;span class="w"&gt; &lt;/span&gt;-verbose&lt;span class="w"&gt; &lt;/span&gt;-CAfile&lt;span class="w"&gt; &lt;/span&gt;root.pem&lt;span class="w"&gt; &lt;/span&gt;-untrusted&lt;span class="w"&gt; &lt;/span&gt;intermediate.pem&lt;span class="w"&gt; &lt;/span&gt;server.pem
server.pem:&lt;span class="w"&gt; &lt;/span&gt;OK
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If there is some issue with validation OpenSSL will throw an error with relevant information.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we learnt how to get certificates from the server and validate them with the root certificate using OpenSSL.&lt;/p&gt;</description><category>command-line</category><guid>https://avilpage.com/2019/11/verify-tls-certificate-chain-with-openssl.html</guid><pubDate>Sat, 30 Nov 2019 04:45:14 GMT</pubDate></item><item><title>Writing &amp; Editing Code With Code - Part 1</title><link>https://avilpage.com/2019/10/writing-editing-code-with-code.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;In Python community, metaprogramming is often used in conjunction with metaclasses. In this article, we will learn about metaprogramming, where programs have the ability to treat other programs as data.&lt;/p&gt;
&lt;h4&gt;Metaprogramming&lt;/h4&gt;
&lt;p&gt;When we start writing programs that write programs, it opens up a lot of possibilities. For example, here is a metaprogramme that generates a program to print numbers from 1 to 100.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'num.py'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'print(&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;)'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This 3 lines of program generates a hundred line of program which produces the desired output on executing it.&lt;/p&gt;
&lt;p&gt;This is a trivial example and is not of much use. Let us see practical examples where metaprogramming is used in Django for admin, ORM, inspectdb and other places.&lt;/p&gt;
&lt;h4&gt;Metaprogramming In Django&lt;/h4&gt;
&lt;p&gt;Django provides a management command called &lt;code&gt;inspectdb&lt;/code&gt; which generates Python code based on SQL schema of the database.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;./manage.py&lt;span class="w"&gt; &lt;/span&gt;inspectdb

from&lt;span class="w"&gt; &lt;/span&gt;django.db&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;models

class&lt;span class="w"&gt; &lt;/span&gt;Book&lt;span class="o"&gt;(&lt;/span&gt;models.Model&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;models.CharField&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;slug&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;models.SlugField&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;...
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In django admin, models can be registered like this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;book.models&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;


&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Eventhough, we have not written any HTML, Django will generate entire CRUD interface for the model in the admin. Django Admin interface is a kind of metaprogramme which inspects a model and generates a CRUD interface.&lt;/p&gt;
&lt;p&gt;Django ORM generates SQL statements for given ORM statements in Python.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"last_login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_superuser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_staff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"date_joined"&lt;/span&gt;
  &lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;
 &lt;span class="n"&gt;ORDER&lt;/span&gt; &lt;span class="n"&gt;BY&lt;/span&gt; &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="n"&gt;DESC&lt;/span&gt;
 &lt;span class="n"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;


&lt;span class="n"&gt;Execution&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.050304&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;anand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Some frameworks/libraries use metaprogramming to solve problems realted to generating, modifying and transforming code.&lt;/p&gt;
&lt;p&gt;We can also use these techniques in everyday programming. Here are some use cases.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate REST API automatically.&lt;/li&gt;
&lt;li&gt;Automatically generate unit test cases based on a template.&lt;/li&gt;
&lt;li&gt;Generate integration tests automatically from the network traffic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are a some of the things related to web development where we can use metaprogramming techniques to generate/modify code. We will learn more about this in the next part of the article.&lt;/p&gt;</description><category>python</category><guid>https://avilpage.com/2019/10/writing-editing-code-with-code.html</guid><pubDate>Thu, 31 Oct 2019 15:51:21 GMT</pubDate></item><item><title>Tips On Writing Data Migrations in Django Application</title><link>https://avilpage.com/2019/09/django-tips-data-migrations.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In a Django application, when schema changes Django automatically generates a migration file for the schema changes. We can write additional migrations to change data.&lt;/p&gt;
&lt;p&gt;In this article, we will learn some tips on writing &lt;a href="https://docs.djangoproject.com/en/dev/topics/migrations/#data-migrations"&gt;data migrations in Django applications&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Use Management Commands&lt;/h4&gt;
&lt;p&gt;Applications can register custom actions with &lt;code&gt;manage.py&lt;/code&gt; by creating a file in &lt;code&gt;management/commands&lt;/code&gt; directory of the application. This makes it easy to (re)run and test data migrations.&lt;/p&gt;
&lt;p&gt;Here is a management command which migrates the &lt;code&gt;status&lt;/code&gt; column of a &lt;code&gt;Task&lt;/code&gt; model.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.core.management.base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseCommand&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;library.tasks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;status_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'valid'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'ACTIVE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'invalid'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'ERROR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'unknown'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'UKNOWN'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the migration is included in Django migration files directly, we have to rollback and re-apply the entire migration which becomes cubersome.&lt;/p&gt;
&lt;h4&gt;Link Data Migrations &amp;amp; Schema Migrations&lt;/h4&gt;
&lt;p&gt;If a data migration needs to happen before/after a specific schema migration, include the migration command using &lt;a href="https://docs.djangoproject.com/en/dev/ref/migration-operations/#django.db.migrations.operations.RunPython"&gt;RunPython&lt;/a&gt; in the same schema migration or create seperate schema migration file and add schema migration as a dependency.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;run_migrate_task_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema_editor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;library.core.management.commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;migrate_task_status&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;migrate_task_status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunPython&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_migrate_task_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RunSQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;noop&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Watch Out For DB Queries&lt;/h4&gt;
&lt;p&gt;When working on a major feature that involves a series of migrations, we have to be careful with data migrations(which use ORM) coming in between schema migrations.&lt;/p&gt;
&lt;p&gt;For example, if we write a data migration script and then make schema changes to the same table in one go, then the migration script fails as Django ORM will be in invalid state for that data migration.&lt;/p&gt;
&lt;p&gt;To overcome this, we can explicitly select only required fields and process them while ignoring all other fields.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# instead of&lt;/span&gt;
&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# use&lt;/span&gt;
&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'is_active'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As an alternative, we can use raw SQL queries for data migrations.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen some of the problems which occur during data migrations in Django applications and tips to alleviate them.&lt;/p&gt;</description><category>django</category><category>django-tips-tricks</category><guid>https://avilpage.com/2019/09/django-tips-data-migrations.html</guid><pubDate>Mon, 30 Sep 2019 15:51:21 GMT</pubDate></item><item><title>Profiling &amp; Optimizing Bottlenecks In Django</title><link>https://avilpage.com/2019/08/django-profile-optimize-views.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;In the previous article, we have learnt where to start with &lt;a href="https://avilpage.com/2018/12/django-bottleneck-performance-scaling.html"&gt;performance optimization in django application&lt;/a&gt; and find out which APIs to optimize first. In this article, we will learn how to optimize those selected APIs from the application.&lt;/p&gt;
&lt;h4&gt;Profling APIs With django-silk&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/django-silk/"&gt;django-silk&lt;/a&gt; provides &lt;code&gt;silk_profile&lt;/code&gt; function which can be used to profile selected view or a snippet of code. Let's take a slow view to profile and see the results.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;silk.profiling.profiler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;silk_profile&lt;/span&gt;


&lt;span class="nd"&gt;@silk_profile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;slow_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;'data'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'slow_response'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We need to add relevant silk settings to django settings so that required profile data files are generated and stored in specified locations.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;SILKY_PYTHON_PROFILER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;SILKY_PYTHON_PROFILER_BINARY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;SILKY_PYTHON_PROFILER_RESULT_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'/tmp/'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the above view is loaded, we can see the profile information in silk profiling page.&lt;/p&gt;
&lt;p&gt;In profile page, silk shows a profile graph and highlights the path where more time is taken.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-profiling1.png"&gt;
&lt;/p&gt;

&lt;p&gt;It also shows cprofile stats in the same page. This profile data file can be downloaded and used with other visualization tools like snakeviz.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-profiling2.png"&gt;
&lt;/p&gt;

&lt;p&gt;By looking at the above data, we can see most of the time is spent is &lt;code&gt;time.sleep&lt;/code&gt; in our view.&lt;/p&gt;
&lt;h4&gt;Profling APIs With django-extensions&lt;/h4&gt;
&lt;p&gt;If you don't want to use silk, an alternate way to profile django views is to use &lt;code&gt;runprofileserver&lt;/code&gt; command provided by &lt;a href="https://pypi.org/project/django-extensions/"&gt;django-extensions&lt;/a&gt; package. Install django-extensions package and then start server with the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;./manage.py&lt;span class="w"&gt; &lt;/span&gt;runprofileserver&lt;span class="w"&gt; &lt;/span&gt;--use-cprofile&lt;span class="w"&gt; &lt;/span&gt;--nostatic&lt;span class="w"&gt; &lt;/span&gt;--prof-path&lt;span class="w"&gt; &lt;/span&gt;/tmp/prof/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command starts runserver with profiling tools enabled. For each request made to the server, it will save a corresponding &lt;code&gt;.prof&lt;/code&gt; profile data file in &lt;code&gt;/tmp/prof/&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;After profile data is generated, we can use profile data viewing tools like &lt;a href="https://pypi.org/project/snakeviz/"&gt;snakeviz&lt;/a&gt;, &lt;a href="https://pypi.org/project/cprofilev/"&gt;cprofilev&lt;/a&gt; visualize or browse the profile data.&lt;/p&gt;
&lt;p&gt;Install snakeviz using pip&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;snakeviz
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open the profile data file using snakeviz.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;snakeviz&lt;span class="w"&gt; &lt;/span&gt;/tmp/prof/api.book.list.4212ms.1566922008.prof
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It shows icicles graph view and  table view of profile data of that view.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-profiling3.png"&gt;
&lt;/p&gt;

&lt;p&gt;These will help to pinpoint which line of code is slowing down the view. Once it is identified, we can take appropriate action like optimize that code, setting up a cache or moving it to a task queue if it is not required to be performed in the request-response cycle.&lt;/p&gt;</description><category>django</category><category>profiling</category><category>python</category><guid>https://avilpage.com/2019/08/django-profile-optimize-views.html</guid><pubDate>Sat, 31 Aug 2019 15:51:21 GMT</pubDate></item><item><title>Versioning &amp; Retrieving Files From AWS S3 With Boto</title><link>https://avilpage.com/2019/07/aws-s3-bucket-objects-versions.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://aws.amazon.com/s3/"&gt;Amazon S3&lt;/a&gt; (Amazon Simple Storage Service) is an object storage service offered by Amazon Web Services. For S3 buckets, if versioning is enabled, users can preserve, retrieve, and restore every version of the object stored in the bucket.&lt;/p&gt;
&lt;p&gt;In this article, we will understand how to enable versioning for a bucket and retrieve all versions of an object from AWS web interface as well as &lt;a href="https://pypi.org/project/boto3/"&gt;Python boto&lt;/a&gt; library.&lt;/p&gt;
&lt;h4&gt;Versioning of Bucket&lt;/h4&gt;
&lt;p&gt;Bucket versioning can be changed with a toggle button from the AWS web console in the bucket properties.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/aws-s3-bucket-version1.png"&gt;
&lt;/p&gt;

&lt;p&gt;We can do the same with Python boto3 library.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;boto3&lt;/span&gt;


&lt;span class="n"&gt;bucket_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'avilpage'&lt;/span&gt;

&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'s3'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;versioning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BucketVersioning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# check status&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;versioning&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# enable versioning&lt;/span&gt;
&lt;span class="n"&gt;versioning&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# disable versioning&lt;/span&gt;
&lt;span class="n"&gt;versioning&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Retrieving Objects&lt;/h4&gt;
&lt;p&gt;Once versioning is enabled, we can store multiple versions of an object by uploading an object multiple times with the same key.&lt;/p&gt;
&lt;p&gt;We can write a simple script to generate a text file with a random text and upload it to S3.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;string&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test.txt'&lt;/span&gt;
&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt;
&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'s3'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_letters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upload_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If this script is executed multiple times, the same file gets overridden with a different version id with the same key in the bucket.&lt;/p&gt;
&lt;p&gt;We can see all the versions of the file from the bucket by selecting the file and then clicking drop-down at &lt;code&gt;Latest version&lt;/code&gt;.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/aws-s3-bucket-version2.png"&gt;
&lt;/p&gt;

&lt;p&gt;We can write a script to retrieve and show contents of all the versions of the test.txt file with the following script.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;boto3&lt;/span&gt;


&lt;span class="n"&gt;bucket_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'avilpage'&lt;/span&gt;
&lt;span class="n"&gt;s3_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'s3'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;versions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_object_versions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;version_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Versions'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'VersionId'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;file_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Versions'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'Key'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;file_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;VersionId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;version_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Body'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Object versioning is useful to protect data from unintended overwrites. In this article, we learnt how to change bucket versioning, upload multiple versions of same file and retrieving all versions of the file using AWS web console as well as boto3.&lt;/p&gt;</description><category>aws</category><category>devops</category><category>python</category><guid>https://avilpage.com/2019/07/aws-s3-bucket-objects-versions.html</guid><pubDate>Wed, 24 Jul 2019 15:51:21 GMT</pubDate></item><item><title>Why My Grandma Can Recall 100+ Phone Numbers, But We Can't</title><link>https://avilpage.com/2019/05/total-recall-grandma-phone-numbers.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;On a leisure evening, as I was chit chatting with my grandma, my phone started ringing. Some one who is not in my contacts is calling me. As I was wondering who the heck is calling, my grandma just glanced at my screen and said, "Its you uncle Somu, pick up the phone". I was dumbstruck by this.&lt;/p&gt;
&lt;p&gt;Later that evening, I asked my grandma to recall the phone numbers she remembers. She recalled 30+ phone numbers and she was able to recognize 100+ phone numbers based on the last 4 digits of the mobile.&lt;/p&gt;
&lt;p&gt;That came as a surprise for me as I don't even remember 10+ phone numbers now. Most of the smart phone users don't remember family and friends phone numbers anymore.&lt;/p&gt;
&lt;p&gt;A decade back, I used to remember most of my relatives and friends phone numbers even though I didn't had a phone. My grandma used to use a mini notebook to write all the phone numbers. I was worried about this mini notebook as it can get lost easily and it is always hard to find when required.&lt;/p&gt;
&lt;p&gt;Since my grandma didn't have any contacts in her phone, she gets a glimpse of number every time someone calls her. She also dials the number every time she has to call someone. With this habit she is able to memorize all the numbers.&lt;/p&gt;
&lt;p&gt;I, on the other hand started using a smart phone which has all the contacts. I search my contacts by name when I have to dial someone and there is no need to dial the number. Also whenever someone call me, their name gets displayed in large letters and I never get to focus on the number. Due to this, I don't remember any of the phone numbers&lt;/p&gt;
&lt;p&gt;After this revelation, I started an experiment by disabling contact permissions for dialer app. With this, I am forced to type the number or select appropriate number from the call history and dial it. This was a bit uncomfortable at first. Soon I got used to it as recognized more and more numbers.&lt;/p&gt;
&lt;p&gt;This might seem unnecessary in the smart phone age. But when you are traveling or when your phone gets switched off, it's hard to contact people. Even if someone gives their phone, it is of no use if I don't remember any numbers.&lt;/p&gt;
&lt;p&gt;Also it is important to remember phone numbers of family and friends which might be needed in case of emergencies.&lt;/p&gt;</description><category>musings</category><guid>https://avilpage.com/2019/05/total-recall-grandma-phone-numbers.html</guid><pubDate>Thu, 20 Jun 2019 15:51:21 GMT</pubDate></item><item><title>Switching Hosts With Bookmarklets - Web Development Tips</title><link>https://avilpage.com/2019/05/environment-bookmarklet-web-development-tips.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When debugging an issue related to web development projects, which is inconsistent between environments (local, development, QA, staging and production), we have to frequently switch between them.&lt;/p&gt;
&lt;p&gt;If we are debugging something on the home page, then we can just bookmark the host URLs. We can switch between them by clicking on the relevant bookmark. Some browsers provide autocompletion for bookmarks. So we can type a few characters and then select the relevant URL from suggestions.&lt;/p&gt;
&lt;p&gt;When debugging an issue on some other page like &lt;a href="https://avilpage.com/2019/05/environment-bookmarklet-web-development-tips.html"&gt;https://avilpage.com/validate/books/?name=darwin&amp;amp;year=2019&lt;/a&gt;, which has URL path and query param, switching between enviroment becomes tedious. To switch to local environment, we have to manually replace the hostname with localhost.&lt;/p&gt;
&lt;p&gt;To avoid this, we can use a bookmarklet to switch the hosts. A &lt;a href="https://en.wikipedia.org/wiki/Bookmarklet"&gt;bookmarklet&lt;/a&gt; is a bookmark which contains a JavaScript code snippet in its URL. This code snippet will be executed when the bookmarklet is clicked.&lt;/p&gt;
&lt;p&gt;Lets create a bookmarklet to replace host in the URL with &lt;a href="http://localhost:8000"&gt;http://localhost:8000&lt;/a&gt;. Create new bookmark called &lt;code&gt;To Local&lt;/code&gt; and in the URL add the following snippet.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8000"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we click on &lt;code&gt;To Local&lt;/code&gt; bookmarklet, it will redirect the current active page to localhost URL.&lt;/p&gt;
&lt;p&gt;We can create one more bookmarklet to switch to production. Create a bookmarklet called &lt;code&gt;To Production&lt;/code&gt; and add the following snippet in the URL.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://avilpage.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create similar bookmarklets to switch to other environments. Now, switching between environments on any page is as easy as clicking a button.&lt;/p&gt;</description><category>browser</category><category>javascript</category><guid>https://avilpage.com/2019/05/environment-bookmarklet-web-development-tips.html</guid><pubDate>Wed, 08 May 2019 15:40:52 GMT</pubDate></item><item><title>A Short Guide To Debugging PostgreSQL Triggers</title><link>https://avilpage.com/2019/04/how-to-debug-postgres-triggers.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/9.1/sql-createtrigger.html"&gt;PostgreSQL triggers&lt;/a&gt; will associate a &lt;code&gt;function&lt;/code&gt; to a table for an event. If multiple triggers of the same kind are defined for the same event, they will be executed in alphabetical order by name.&lt;/p&gt;
&lt;p&gt;In this article, we will see how to debug PostgreSQL triggers.&lt;/p&gt;
&lt;h4&gt;Triggers&lt;/h4&gt;
&lt;p&gt;First, ensure triggers are enabled on the required tables for INSERT/UPDATE/DELETE events. We can check available triggers by running the following query.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;triggers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also use &lt;code&gt;EXPLAIN&lt;/code&gt; to show triggers that are executed for an event by running relevant queries.&lt;/p&gt;
&lt;h4&gt;PostgreSQL Logging&lt;/h4&gt;
&lt;p&gt;After ensuring triggers are applied correctly, set the logging level for postgresql server and client in postgres.conf file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;
&lt;span class="n"&gt;log_statement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'all'&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;level&lt;/span&gt;
&lt;span class="n"&gt;client_min_messages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart PostgreSQL to reflect configuration changes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Linux&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;service&lt;span class="w"&gt; &lt;/span&gt;postgres&lt;span class="w"&gt; &lt;/span&gt;restart

&lt;span class="c1"&gt;# Mac&lt;/span&gt;
brew&lt;span class="w"&gt; &lt;/span&gt;services&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;postgres
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Tail the logs and check if queries are executing correctly with appropriate values.&lt;/p&gt;
&lt;h4&gt;Triggers Logging&lt;/h4&gt;
&lt;p&gt;After enabling logging for PostgreSQL, we can &lt;a href="https://www.postgresql.org/docs/9.0/plpgsql-errors-and-messages.html"&gt;raise messages/errors in triggers&lt;/a&gt; so that we can see if any unexpected things are happening at any point in the trigger.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;RAISE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Updating row with ID: %'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;RAISE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;division_by_zero&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;RAISE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;WARNING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Unable to delete record'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This ensures triggers are executing as expected and if there are any warnings/errors, it will log a message.&lt;/p&gt;
&lt;h4&gt;SQL/PostgreSQL Gotchas&lt;/h4&gt;
&lt;p&gt;Even though queries and triggers are executing correctly, we might not see the desired result because of the potentially surprising behavior of PostgreSQL. There are some scenarios where PostgreSQL seems to be not working at first but it actually is the expected behavior.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unquoted object names will be treated as lowercase. &lt;code&gt;SELECT FOO FROM bar&lt;/code&gt; will become &lt;code&gt;SELECT foo FROM bar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Comparing nullable fields. This might yield strange results as &lt;code&gt;NULL != NULL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;PostgreSQL uses POSIX offsets. For &lt;code&gt;04:21:42 UTC+01&lt;/code&gt;, +1  means the timezone is west of Greenwich.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;By being aware of common PostgreSQL gotchas and enabling logging for PostgreSQL clients, servers &amp;amp; triggers, pinpointing the bug in triggers becomes easy. Once the bug is identified, appropriate action can be taken to fix the issue.&lt;/p&gt;
&lt;!-- links --&gt;</description><category>database</category><category>debugging</category><category>postgresql</category><guid>https://avilpage.com/2019/04/how-to-debug-postgres-triggers.html</guid><pubDate>Tue, 30 Apr 2019 15:51:21 GMT</pubDate></item><item><title>Essential PyCharm (Intellij) Plugins To Improve Productivity</title><link>https://avilpage.com/2019/03/intellij-pycharm-plugins-productivity.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;As per 2019 &lt;a href="https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools"&gt;JetBrains survery&lt;/a&gt;, PyCharm is the most widely used(36%) IDE for Python development. Even though PyCharm comes with a lot of built-in features, there are a lot of plugins available for PyCharm and other Intellij IDEs. In this article, we will see some plugins which will boost our productivity during development.&lt;/p&gt;
&lt;h4&gt;Ace Jump&lt;/h4&gt;
&lt;p&gt;To move caret to a particular position in the editor without mouse,
&lt;a href="https://plugins.jetbrains.com/plugin/7086-acejump"&gt;AceJump plugin&lt;/a&gt; will be useful. It allows to quickly navigate the caret to any position in the editor.&lt;/p&gt;
&lt;h4&gt;GitToolBox&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://plugins.jetbrains.com/plugin/7499-gittoolbox"&gt;GitToolBox&lt;/a&gt; provides a lot of additional features like inblame support, status bar widget, commit dialog, branch name completion, etc.&lt;/p&gt;
&lt;h4&gt;Grep Console&lt;/h4&gt;
&lt;p&gt;When running a django/flask server or any Python script which generates a lot of output, it is hard to filter specific output on console. &lt;a href="https://plugins.jetbrains.com/plugin/7125-grep-console"&gt;Grep Console&lt;/a&gt; can filter or highlight output based on specific conditions which makes it easier to debug the code.&lt;/p&gt;
&lt;h4&gt;Highlight Bracket Pair&lt;/h4&gt;
&lt;p&gt;Instead of manually scanning where a bracket starts/ends, &lt;a href="https://plugins.jetbrains.com/plugin/10465-highlightbracketpair"&gt;Highlight Bracket Pair&lt;/a&gt; will automatically highlight the bracket pairs based on cursor position.&lt;/p&gt;
&lt;h4&gt;Key Promoter&lt;/h4&gt;
&lt;p&gt;If you are new to PyCharm or an experienced user who is using mouse instead of key board shortcuts, &lt;a href="https://plugins.jetbrains.com/plugin/9792-key-promoter-x"&gt;Key Promoter&lt;/a&gt; will show relevant key board shortcut when mouse is used inside IDE. This provides an easy way to learn keyboard shortcuts faster.&lt;/p&gt;
&lt;h4&gt;Rainbow Brackets&lt;/h4&gt;
&lt;p&gt;Highlight Bracket Pair will hightlight the bracket pair around the cursor. When there are multiple bracket pairs deeply nested, &lt;a href="https://plugins.jetbrains.com/plugin/10080-rainbow-brackets"&gt;Rainbow Brackets&lt;/a&gt; will highlight matching bracket pairs with matching rainbow colors.&lt;/p&gt;
&lt;h4&gt;Save Actions&lt;/h4&gt;
&lt;p&gt;Instead of manually optimizing imports or reformatting code when changes are made, we can use &lt;a href="https://plugins.jetbrains.com/plugin/7642-save-actions"&gt;Save Actions&lt;/a&gt; which will automatically run a set of actions on every file save.&lt;/p&gt;
&lt;h4&gt;String Manipulation&lt;/h4&gt;
&lt;p&gt;To convert lower case letters to upper case letter, &lt;a href="https://plugins.jetbrains.com/plugin/2162-string-manipulation"&gt;String manipulation plugin&lt;/a&gt; will be useful. In addition to lower/upper case conversion, it also provides options to convert to cameCase, kebab-case, PascalCase etc.&lt;/p&gt;
&lt;p&gt;These are some plugins which will boost developers productivity while writing and debugging code in PyCharm or other JetBrains IDE.&lt;/p&gt;</description><category>python</category><guid>https://avilpage.com/2019/03/intellij-pycharm-plugins-productivity.html</guid><pubDate>Sun, 31 Mar 2019 15:51:21 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #12 - Automatically Set CSRF Token in Postman</title><link>https://avilpage.com/2019/02/django-tips-csrf-token-postman-curl.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Django has inbuilt &lt;a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;CSRF protection&lt;/a&gt; mechanism for requests via unsafe methods to prevent &lt;a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;Cross Site Request Forgeries&lt;/a&gt;. When CSRF protection is enabled on AJAX POST methods, &lt;code&gt;X-CSRFToken&lt;/code&gt; header should be sent in the request.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.getpostman.com"&gt;Postman&lt;/a&gt; is one of the widely used tool for testing APIs. In this article, we will see how to set csrf token and update it automatically in Postman.&lt;/p&gt;
&lt;h4&gt;CSRF Token In Postman&lt;/h4&gt;
&lt;p&gt;Django sets &lt;code&gt;csrftoken&lt;/code&gt; cookie on login. After logging in, we can see the csrf token from cookies in the Postman.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-csrf-postman1.png"&gt;
&lt;/p&gt;

&lt;p&gt;We can grab this token and set it in headers manually.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-csrf-postman2.png"&gt;
&lt;/p&gt;

&lt;p&gt;But this token has to be manually changed when it expires. This process becomes tedious to do it on an expiration basis.&lt;/p&gt;
&lt;p&gt;Instead, we can use Postman scripting feature to extract token from cookie and set it to an environment variable. In &lt;code&gt;Test&lt;/code&gt; section of postman, add these lines.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xsrfCookie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;postman&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getResponseCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"csrftoken"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;postman&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'csrftoken'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xsrfCookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This extracts csrf token and sets it to an environment variable called &lt;code&gt;csrftoken&lt;/code&gt; in the current environment.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-csrf-postman3.png"&gt;
&lt;/p&gt;

&lt;p&gt;Now in our requests, we can use this variable to set the header.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-csrf-postman4.png"&gt;
&lt;/p&gt;

&lt;p&gt;When the token expires, we just need to login again and csrf token gets updated automatically.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article we have seen how to set and renew csrftoken automatically in Postman. We can follow similar techniques on other API clients like CURL or httpie to set csrf token.&lt;/p&gt;</description><category>automation</category><category>django</category><category>python</category><guid>https://avilpage.com/2019/02/django-tips-csrf-token-postman-curl.html</guid><pubDate>Thu, 28 Feb 2019 15:51:21 GMT</pubDate></item><item><title>How To Install Private Python Packages With Pip</title><link>https://avilpage.com/2018/11/how-to-install-private-python-packages-with-pip.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;To distribute python code, we need to package it and host it somewhere, so that users can install and use it. If the code is public, it can be published to &lt;a href="https://pypi.org"&gt;PyPi&lt;/a&gt; or any public repository, so that anyone can access it. If the code is private, we need to provide proper authentication mechanism before allowing users to access it.&lt;/p&gt;
&lt;p&gt;In this article, we will see how to use &lt;a href="https://packaging.python.org/key_projects/#pip"&gt;pip&lt;/a&gt; to install Python packages hosted on GitLab, GitHub, Bitbucket or any other services.&lt;/p&gt;
&lt;h4&gt;Packaging&lt;/h4&gt;
&lt;p&gt;To package python project, we need to create &lt;code&gt;setup.py&lt;/code&gt; file which is build script for setuptools. Below is a sample setup file to create a package named &lt;code&gt;library&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;setuptools&lt;/span&gt;


&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"README.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;long_description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;setuptools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"chillaranand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;author_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"foo@avilpage.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"A simple python package"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;long_description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;long_description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/chillaranand/library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;setuptools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_packages&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;classifiers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"Programming Language :: Python :: 3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"License :: OSI Approved :: MIT License"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Operating System :: OS Independent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python provides &lt;a href="https://packaging.python.org/tutorials/packaging-projects/"&gt;detailed packaging documentation&lt;/a&gt; on structuring and building the package.&lt;/p&gt;
&lt;h4&gt;Installation&lt;/h4&gt;
&lt;p&gt;Once module(s) is packaged and pushed to hosting service, it can be installed with pip.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# using https&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;git+https://github.com/chillaranand/library.git

&lt;span class="c1"&gt;# using ssh&lt;/span&gt;
pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;git+ssh://git@github.com/chillaranand/library.git
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This usually requires authentication with usersname/password or ssh key. This setup works for developement machines. To use it in CI/CD pipelines or as a dependency, we can use tokens to simplify installation.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;foobar

$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;git+https://&lt;span class="nv"&gt;$GITHUB_TOKEN&lt;/span&gt;@github.com/chillaranand/library.git
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how to package python code and install private packages with pip. This makes it easy to manage dependencies or install packages on multiple machines.&lt;/p&gt;</description><category>devops</category><category>python</category><guid>https://avilpage.com/2018/11/how-to-install-private-python-packages-with-pip.html</guid><pubDate>Thu, 31 Jan 2019 06:42:12 GMT</pubDate></item><item><title>Find High-impact Performance Bottlenecks in Django</title><link>https://avilpage.com/2018/12/django-bottleneck-performance-scaling.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;When optimizing performance of web application, a common mistake is to start with optimizing the slowest page(or API). In addition to considering response time, we should also consider the traffic it is receving to priorotize the order of optimization.&lt;/p&gt;
&lt;p&gt;In this article we will profile a django webapp, find high-impact performance bottlenecks and then start optimization them to yield better performance.&lt;/p&gt;
&lt;h4&gt;Profiling&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/jazzband/django-silk"&gt;django-silk&lt;/a&gt; is an open source profiling tool which intercepts and stores HTTP requests data. Install it with pip.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;django-silk
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;silk&lt;/code&gt; to installed apps and include silk middleware in django settings.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;MIDDLEWARE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="s1"&gt;'silk.middleware.SilkyMiddleware'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="s1"&gt;'silk'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Run migrations so that Silk can create required database tables to store profile data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;manage.py&lt;span class="w"&gt; &lt;/span&gt;makemigrations
$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;manage.py&lt;span class="w"&gt; &lt;/span&gt;migrate
$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;manage.py&lt;span class="w"&gt; &lt;/span&gt;collectstatic
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Include silk urls in root urlconf to view the profile data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'^silk/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'silk.urls'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'silk'&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On silk requests page(&lt;a href="https://avilpage.com/2018/12/django-bottleneck-performance-scaling.html"&gt;http://host/silk/requests/&lt;/a&gt;), we can see all requests and sort them by overall time or time spent in database.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-bottlenecks.png"&gt;
&lt;/p&gt;

&lt;h4&gt;High Impact Bottlenecks&lt;/h4&gt;
&lt;p&gt;Silk creates &lt;code&gt;silk_request&lt;/code&gt; table which contains information about the requests processed by django.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pgcli&lt;/span&gt;

&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;silk_request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;--------------------+--------------------------+-------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Column&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Type&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Modifiers&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="c1"&gt;--------------------+--------------------------+-------------|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;character&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;varying&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;character&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;varying&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;190&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time_taken&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;precision&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can group these requests data by &lt;code&gt;path&lt;/code&gt;, calculate number of requests, average time taken and impact factor of each path. Since we are considering response time and traffic, impact factor will be product of average response time and number of requests for that path.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avg_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avg_time&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()::&lt;/span&gt;&lt;span class="nb"&gt;NUMERIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;impact&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time_taken&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;avg_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;silk_request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;impact&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;-------------------------+------------+---------+----------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;avg_time&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;impact&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="c1"&gt;-------------------------+------------+---------+----------|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;239&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1400&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;94&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1900&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;152&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;307&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;106&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;494&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can see &lt;code&gt;/point/book/book/&lt;/code&gt; has highest impact even though it is neighter most visited nor slowest view. Optimizing this view first yields in overall better performance of webapp.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we learnt how to profile django webapp and identify bottlenecks to improve performance. In the next article, we wil learn how to optimize these bottlenecks by taking an in-depth look at them.&lt;/p&gt;</description><category>django</category><category>featured</category><category>profiling</category><category>python</category><guid>https://avilpage.com/2018/12/django-bottleneck-performance-scaling.html</guid><pubDate>Tue, 11 Dec 2018 02:38:08 GMT</pubDate></item><item><title>Archive Million Pages With wget In Minutes</title><link>https://avilpage.com/2018/11/archive-millions-pages-wget-minutes.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://github.com/webrecorder/webrecorder"&gt;webrecorder&lt;/a&gt;, &lt;a href="https://github.com/internetarchive/heritrix3"&gt;heritrix&lt;/a&gt;, &lt;a href="https://nutch.apache.org/"&gt;nutch&lt;/a&gt;, &lt;a href="https://scrapy.org/"&gt;scrapy&lt;/a&gt;, &lt;a href="https://github.com/gocolly/colly"&gt;colly&lt;/a&gt;, &lt;a href="https://github.com/scrapinghub/frontera"&gt;frontera&lt;/a&gt; are popular tools for large scale web crawling and archiving.&lt;/p&gt;
&lt;p&gt;These tools require some learning curve and some of them don't have inbuilt support for warc(&lt;a href="https://en.wikipedia.org/wiki/Web_ARChive"&gt;Web ARChive&lt;/a&gt;) output format.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wget&lt;/code&gt; comes bundled with most *nix systems and has inbuilt support for warc output. In this article we will see how to quickly archive web pages with wget.&lt;/p&gt;
&lt;h4&gt;Archiving with wget&lt;/h4&gt;
&lt;p&gt;In previous article we have extracted a &lt;a href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html"&gt;superset of top 1 million domains&lt;/a&gt;. We can use that list or urls to archive. Save this list to a file called &lt;code&gt;urls.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This can be archived with the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;urls.txt
wget&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--warc-file&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--timeout&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;/dev/null
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;wget has the ability to continue partially downloaded files. But this option won't work with warc output. So, it is better to split this list into small chunks and process them. One added advantage of this approach is we can parallely download multiple chunks with wget.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;chunks
split&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;urls.txt&lt;span class="w"&gt; &lt;/span&gt;chunks/&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--additional-suffix&lt;span class="o"&gt;=&lt;/span&gt;.txt&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will split the file into several chunks each containing 1000 urls. wget doesn't have multithreading support. We can write a for loop to schedule a seperate process for each chunk.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;for file in &lt;span class="sb"&gt;`ls -r chunks/*.txt`&lt;/span&gt;
do
   wget -i $file --warc-file=$file -t 3 --timeout=4 -q -o /dev/null -O /dev/null &amp;amp;
done
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To archive 1000 urls, it takes ~15 minutes. In less than 20 minutes, it will download entire million pages.&lt;/p&gt;
&lt;p&gt;Also, each process takes ~8MB of memory. To run 1000 process, a system needs 8GB+ memory. Otherwise, number of parallel processes should be reduced which increases overall run time.&lt;/p&gt;
&lt;p&gt;Each archive chunk will be ~150MB and consume lot of storage. All downloaded acrhives can be zipped to reduce storage.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;gzip&lt;span class="w"&gt; &lt;/span&gt;*.warc
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is an idempotent shell script to download and archive files in batches.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#! /bin/sh&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-x

&lt;span class="nv"&gt;batch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;expr&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;batch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nv"&gt;maxproc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;
&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;urls.txt
&lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s1"&gt;'/projects/chunks'&lt;/span&gt;&lt;span class="nv"&gt;$batch&lt;/span&gt;


mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;
split&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$batch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--additional-suffix&lt;span class="o"&gt;=&lt;/span&gt;.txt&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$size&lt;/span&gt;
sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="nv"&gt;useragent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'&lt;/span&gt;


&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;/*.txt&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;warcfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s1"&gt;'.warc'&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;warczip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$warcfile&lt;/span&gt;&lt;span class="s1"&gt;'.gz'&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$warczip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$warcfile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;pgrep&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-lt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$maxproc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user-agent: &lt;/span&gt;&lt;span class="nv"&gt;$useragent&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--warc-file&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--timeout&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;filename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*.warc'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-mmin&lt;span class="w"&gt; &lt;/span&gt;+5&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;gzip&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-9
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;In this article, we have seen how to archive million pages with wget in few minutes.&lt;/p&gt;
&lt;p&gt;wget2 has multithreading support and &lt;a href="https://gitlab.com/gnuwget/wget2/issues/65"&gt;it might have warc output soon&lt;/a&gt;. With that, archiving with wget becomes much easier.&lt;/p&gt;</description><category>command-line</category><guid>https://avilpage.com/2018/11/archive-millions-pages-wget-minutes.html</guid><pubDate>Sun, 18 Nov 2018 11:51:21 GMT</pubDate></item><item><title>Alexa vs Domcop vs Majestic - Top Million Sites</title><link>https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Alexa&lt;sup id="fnref:alexa"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fn:alexa"&gt;1&lt;/a&gt;&lt;/sup&gt;, Domcop&lt;sup id="fnref:domcop"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fn:domcop"&gt;2&lt;/a&gt;&lt;/sup&gt;(based on CommonCrawl&lt;sup id="fnref:commoncrawl"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fn:commoncrawl"&gt;3&lt;/a&gt;&lt;/sup&gt; data) Majestic&lt;sup id="fnref:majestic"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fn:majestic"&gt;4&lt;/a&gt;&lt;/sup&gt; &amp;amp;  provide top 1 million popular websites based on their analytics. In this article we will download this data and compare them using Linux command line tools.&lt;/p&gt;
&lt;h4&gt;Collecting data&lt;/h4&gt;
&lt;p&gt;Let's download data from above sources and extract domain names. The data format is different for each source. We can use &lt;code&gt;awk&lt;/code&gt; tool to extract domains column from the source. After extracting data, sort it and save it to a file.&lt;/p&gt;
&lt;p&gt;Extracting domains from alexa.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# alexa&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;http://s3.amazonaws.com/alexa-static/top-1m.csv.zip

$&lt;span class="w"&gt; &lt;/span&gt;unzip&lt;span class="w"&gt; &lt;/span&gt;top-1m.csv.zip

&lt;span class="c1"&gt;# data sorted by ranking&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;top-1m.csv
&lt;span class="m"&gt;1&lt;/span&gt;,google.com
&lt;span class="m"&gt;2&lt;/span&gt;,youtube.com
&lt;span class="m"&gt;3&lt;/span&gt;,facebook.com
&lt;span class="m"&gt;4&lt;/span&gt;,baidu.com
&lt;span class="m"&gt;5&lt;/span&gt;,wikipedia.org

$&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{print $2}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;top-1m.csv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;alexa

&lt;span class="c1"&gt;# domains after sorting alphabetically&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;alexa
&lt;span class="m"&gt;00000&lt;/span&gt;.life
&lt;span class="m"&gt;00&lt;/span&gt;-000.pl
&lt;span class="m"&gt;00004&lt;/span&gt;.tel
&lt;span class="m"&gt;00008888&lt;/span&gt;.tumblr.com
0002rick.tumblr.com
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Extracting domain names from domcop.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Domcop&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://www.domcop.com/files/top/top10milliondomains.csv.zip

$&lt;span class="w"&gt; &lt;/span&gt;unzip&lt;span class="w"&gt; &lt;/span&gt;top10milliondomains.csv.zip

&lt;span class="c1"&gt;# data sorted by ranking&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;top10milliondomains.csv
&lt;span class="s2"&gt;"Rank"&lt;/span&gt;,&lt;span class="s2"&gt;"Domain"&lt;/span&gt;,&lt;span class="s2"&gt;"Open Page Rank"&lt;/span&gt;
&lt;span class="s2"&gt;"1"&lt;/span&gt;,&lt;span class="s2"&gt;"fonts.googleapis.com"&lt;/span&gt;,&lt;span class="s2"&gt;"10.00"&lt;/span&gt;
&lt;span class="s2"&gt;"2"&lt;/span&gt;,&lt;span class="s2"&gt;"facebook.com"&lt;/span&gt;,&lt;span class="s2"&gt;"10.00"&lt;/span&gt;
&lt;span class="s2"&gt;"3"&lt;/span&gt;,&lt;span class="s2"&gt;"youtube.com"&lt;/span&gt;,&lt;span class="s2"&gt;"10.00"&lt;/span&gt;
&lt;span class="s2"&gt;"4"&lt;/span&gt;,&lt;span class="s2"&gt;"twitter.com"&lt;/span&gt;,&lt;span class="s2"&gt;"10.00"&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\"*,\"*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{if(NR&amp;gt;1)print $2}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;top10milliondomains.csv.zip&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;domcop

&lt;span class="c1"&gt;# domains after sorting alphabetically&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;domcop
00000000b.com
000000book.com
&lt;span class="m"&gt;0000180&lt;/span&gt;.fortunecity.com
&lt;span class="m"&gt;000139418&lt;/span&gt;.wixsite.com
000fashions.blogspot.com
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Extracting domain names from majestic.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Majestic&lt;/span&gt;

$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;http://downloads.majestic.com/majestic_million.csv

&lt;span class="c1"&gt;# data sorted by ranking&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;majestic_million.csv
GlobalRank,TldRank,Domain,TLD,RefSubNets,RefIPs,IDN_Domain,IDN_TLD,PrevGlobalRank,PrevTldRank,PrevRefSubNets,PrevRefIPs
&lt;span class="m"&gt;1&lt;/span&gt;,1,google.com,com,474277,3016409,google.com,com,1,1,474577,3012875
&lt;span class="m"&gt;2&lt;/span&gt;,2,facebook.com,com,462854,3093315,facebook.com,com,2,2,462860,3090006
&lt;span class="m"&gt;3&lt;/span&gt;,3,youtube.com,com,422434,2504924,youtube.com,com,3,3,422377,2501555
&lt;span class="m"&gt;4&lt;/span&gt;,4,twitter.com,com,412950,2497935,twitter.com,com,4,4,413220,2495261

$&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\"*,\"*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{if(NR&amp;gt;1)print $2}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;majestic_million.csv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sort&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;majestic

&lt;span class="c1"&gt;# domains after sorting alphabetically&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;majestic
&lt;span class="m"&gt;00000&lt;/span&gt;.xn--p1ai
&lt;span class="m"&gt;0000666&lt;/span&gt;.com
&lt;span class="m"&gt;0000&lt;/span&gt;.jp
0000www.com
&lt;span class="m"&gt;0000&lt;/span&gt;.xn--p1ai
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Comparing Data&lt;/h4&gt;
&lt;p&gt;We have collected and extracted domains from above sources. Let's compare the domains to see how similar they are using &lt;code&gt;comm&lt;/code&gt; tool.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;comm&lt;span class="w"&gt; &lt;/span&gt;-123&lt;span class="w"&gt; &lt;/span&gt;alexa&lt;span class="w"&gt; &lt;/span&gt;domcop&lt;span class="w"&gt; &lt;/span&gt;--total
&lt;span class="m"&gt;871851&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;871851&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;128149&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;total

$&lt;span class="w"&gt; &lt;/span&gt;comm&lt;span class="w"&gt; &lt;/span&gt;-123&lt;span class="w"&gt; &lt;/span&gt;alexa&lt;span class="w"&gt; &lt;/span&gt;majestic&lt;span class="w"&gt; &lt;/span&gt;--total
&lt;span class="m"&gt;788454&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;788454&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;211546&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;total

$&lt;span class="w"&gt; &lt;/span&gt;comm&lt;span class="w"&gt; &lt;/span&gt;-123&lt;span class="w"&gt; &lt;/span&gt;domcop&lt;span class="w"&gt; &lt;/span&gt;majestic&lt;span class="w"&gt; &lt;/span&gt;--total
&lt;span class="m"&gt;784388&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;784388&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;215612&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;comm&lt;span class="w"&gt; &lt;/span&gt;-12&lt;span class="w"&gt; &lt;/span&gt;alexa&lt;span class="w"&gt; &lt;/span&gt;domcop&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;comm&lt;span class="w"&gt; &lt;/span&gt;-123&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;majestic&lt;span class="w"&gt; &lt;/span&gt;--total
&lt;span class="m"&gt;31314&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;903165&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;96835&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, only 96,835(9.6%) domains are common between all the datasets and the overlap between any two sources is ~20%. Here is a venn diagram showing the overlap between them.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/million-alexa-majestic-domcop.png"&gt;
&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We have collected data from alexa, domcorp &amp;amp; majestic, extracted domains from it and observed that there is only a small overlap between them.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:alexa"&gt;
&lt;p&gt;&lt;a href="http://s3.amazonaws.com/alexa-static/top-1m.csv.zip"&gt;http://s3.amazonaws.com/alexa-static/top-1m.csv.zip&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fnref:alexa" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:domcop"&gt;
&lt;p&gt;&lt;a href="https://www.domcop.com/files/top/top10milliondomains.csv.zip"&gt;https://www.domcop.com/files/top/top10milliondomains.csv.zip&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fnref:domcop" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:commoncrawl"&gt;
&lt;p&gt;&lt;a href="https://commoncrawl.org/"&gt;https://commoncrawl.org/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fnref:commoncrawl" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:majestic"&gt;
&lt;p&gt;&lt;a href="http://downloads.majestic.com/majestic_million.csv"&gt;http://downloads.majestic.com/majestic_million.csv&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html#fnref:majestic" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>command-line</category><category>data-analysis</category><category>python</category><guid>https://avilpage.com/2018/11/comparision-alexa-majestic-domcorp-top-million-sites.html</guid><pubDate>Fri, 02 Nov 2018 06:34:58 GMT</pubDate></item><item><title>Setup Continous Deployment For Python Chalice</title><link>https://avilpage.com/2018/10/cd-python-chalice-aws.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Outline&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/chalice/"&gt;Chalice&lt;/a&gt; is a microframework developed by Amazon for quickly creating and deploying serverless applications in Python.&lt;/p&gt;
&lt;p&gt;In this article, we will see how to setup continous deployment with &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html"&gt;AWS CodePipeline&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;CD Setup&lt;/h4&gt;
&lt;p&gt;Chalice provides cli command &lt;code&gt;deploy&lt;/code&gt; to deploy from local system.&lt;/p&gt;
&lt;p&gt;Chalice also provides cli command &lt;code&gt;generate-pipeline&lt;/code&gt; command to generate CloudFormation template. This template is useful to automatically generate several resources required for AWS pipeline.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/aws-python-pipeline.png" height="300px" width="600"&gt;
&lt;/p&gt;

&lt;p&gt;This by default uses CodeCommit repository for hosting code. We can use GitHub repo as a source instead of CodeCommit.&lt;/p&gt;
&lt;p&gt;Chalice by default provides a build file to package code and push it to S3. In the deploy step, it uses this artifact to deploy the code.&lt;/p&gt;
&lt;p&gt;We can use a custom buildpsec file to directly deploy the code from build step.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;

&lt;span class="n"&gt;phases&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;install&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Entering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;phase&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Installing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;awscli&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chalice&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entered&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;phase&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`date`&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chalice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;staging&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This buildspec file install requirements and deploys chalice app to staging. We can add one more build step to deploy it production after manual intervention.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;We have seen how to setup continous deployment for chalice application with GitHub and AWS CodePipeline.&lt;/p&gt;</description><category>aws</category><category>devops</category><category>python</category><guid>https://avilpage.com/2018/10/cd-python-chalice-aws.html</guid><pubDate>Tue, 30 Oct 2018 15:51:21 GMT</pubDate></item><item><title>Parsing &amp; Transforming mitmproxy Request Flows</title><link>https://avilpage.com/2018/08/parsing-and-transforming-mitmproxy-request-flows.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;a href="https://mitmproxy.org/"&gt;mitmproxy&lt;/a&gt; is a free and open source interactive HTTPS proxy. It provides command-line interface, web interface and Python API for interaction and customizing it for our needs.&lt;/p&gt;
&lt;p&gt;mitmproxy provides an option to export web request flows to curl/httpie/raw formats. From mitmproxy, we can press &lt;code&gt;e&lt;/code&gt;(export) and then we can select format for exporting.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/mitm-curl.png" height="300px" width="600"&gt;
&lt;/p&gt;

&lt;p&gt;Exporting multiple requests with this interface becomes tedious. Instead we can save all requests to a file and write a python script to export them.&lt;/p&gt;
&lt;p&gt;Start mitmproxy with this command so that all request flows are appended to &lt;code&gt;requests.mitm&lt;/code&gt; file for later use.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;mitmproxy&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;+requests.mitm
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is a python script to parse this dump file and print request URLs.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;mitmproxy.io&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FlowReader&lt;/span&gt;


&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'requests.mitm'&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FlowReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;flow.request&lt;/code&gt; object has more attributes to provide information about the request.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
 &lt;span class="s1"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'host_header'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'http_version'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'multipart_form'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'raw_content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="o"&gt;...&lt;/span&gt;
 &lt;span class="s1"&gt;'wrap'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use the mitmproxy export utilities to transform mitm flows to other formats.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;mitmproxy.addons&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;curl_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s2"&gt;"curl -H 'Host:mitm.it' -H 'Proxy-Connection:keep-alive' -H 'User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' -H 'DNT:1' -H 'Accept:image/webp,image/apng,image/*,*/*;q=0.8' -H 'Referer:http://mitm.it/' -H 'Accept-Encoding:gzip, deflate' -H 'Accept-Language:en-US,en;q=0.9,ms;q=0.8,te;q=0.7' -H 'content-length:0' 'http://mitm.it/favicon.ico'"&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;'GET /favicon.ico HTTP/1.1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Host: mitm.it&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Proxy-Connection: keep-alive&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;DNT: 1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Accept: image/webp,image/apng,image/*,*/*;q=0.8&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Referer: http://mitm.it/&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Accept-Encoding: gzip, deflate&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Accept-Language: en-US,en;q=0.9,ms;q=0.8,te;q=0.7&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;httpie_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s2"&gt;"http GET http://mitm.it/favicon.ico 'Host:mitm.it' 'Proxy-Connection:keep-alive' 'User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' 'DNT:1' 'Accept:image/webp,image/apng,image/*,*/*;q=0.8' 'Referer:http://mitm.it/' 'Accept-Encoding:gzip, deflate' 'Accept-Language:en-US,en;q=0.9,ms;q=0.8,te;q=0.7' 'content-length:0'"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With these utilities we can transform mitmproxy request flow to curl command or any other custom form to fit our needs.&lt;/p&gt;</description><category>python</category><guid>https://avilpage.com/2018/08/parsing-and-transforming-mitmproxy-request-flows.html</guid><pubDate>Sat, 11 Aug 2018 15:51:21 GMT</pubDate></item><item><title>Linux Performance Analysis In Less Than 10 Seconds</title><link>https://avilpage.com/2018/07/linux-performance-analysis-in-seconds.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;If you are using a Linux System or managing a Linux server, you might come across a situation where a process is taking too long to complete. In this article we will see how to track down such performance issues in Linux.&lt;/p&gt;
&lt;p&gt;Netflix TechBlog has an article on how to &lt;a href="https://medium.com/netflix-techblog/linux-performance-analysis-in-60-000-milliseconds-accc10403c55"&gt;anlyze Linux performance in 60 seconds&lt;/a&gt;. This article  provides 10+ tools to use in order to see the resource usage and pinpoint the bottleneck.&lt;/p&gt;
&lt;p&gt;It is strenuous to remember all those tools/options and laborious to run all those commands when working on multiple systems.&lt;/p&gt;
&lt;p&gt;Instead, we can use &lt;a href="http://atoptool.nl/"&gt;atop&lt;/a&gt;, a tool for one stop solution for performance analysis. Here is a comparision of atop with other tools from &lt;a href="https://lwn.net/Articles/387202/"&gt;LWN&lt;/a&gt;.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/linux-performance-analysis-tools.png" height="300px" width="600"&gt;
&lt;/p&gt;

&lt;p&gt;atop shows live &amp;amp; historical data measurement at system level as well as process level. To get the glimpse of system resource(CPU, memory, network, disk) usage install and run atop with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--yes&lt;span class="w"&gt; &lt;/span&gt;atop

$&lt;span class="w"&gt; &lt;/span&gt;atop
&lt;/pre&gt;&lt;/div&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/atop.png" height="300px" width="600"&gt;
&lt;/p&gt;

&lt;p&gt;By default, atop shows resources used in the last interval only and sorts them by CPU usage. We can use&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;atop&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;-A&lt;/code&gt; sorts the processes automatically in the order of the most busy system resource.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-f&lt;/code&gt; shows both active as well as inactive system resources in the ouput.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;4&lt;/code&gt; sets refresh interval to 4 seconds.&lt;/p&gt;
&lt;p&gt;Just by looking at the output of atop, we get a glimpse of overall system resource usage as well as individual processes resource usage.&lt;/p&gt;</description><category>command-line</category><category>linux</category><guid>https://avilpage.com/2018/07/linux-performance-analysis-in-seconds.html</guid><pubDate>Tue, 24 Jul 2018 15:51:21 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #10 - Log SQL Queries To Console</title><link>https://avilpage.com/2018/05/django-tips-tricks-log-sql-queries-to-console.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Django ORM makes easy to interact with database. To understand what is happening behing the scenes or to see SQL performance, we can log all the SQL queries that be being executed. In this article, we will see various ways to achieve this.&lt;/p&gt;
&lt;h4&gt;Using debug-toolbar&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/django-debug-toolbar/" target="_blank"&gt;Django debug toolbar&lt;/a&gt; provides panels to show debug information about requests. It has SQL panel which shows all executed SQL queries and time taken for them.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-sql-log-toolbar.png" height="300px" width="600"&gt;
&lt;/p&gt;

&lt;p&gt;When building REST APIs or micro services where django templating engine is not used, &lt;a href="https://github.com/jazzband/django-debug-toolbar/issues/1059" target="_blank"&gt;this method won't work&lt;/a&gt;. In these situations, we have to log SQL queries to console.&lt;/p&gt;
&lt;h4&gt;Using django-extensions&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/django-extensions/"&gt;Django-extensions&lt;/a&gt; provides lot of utilities for productive development. For &lt;code&gt;runserver_plus&lt;/code&gt; and &lt;code&gt;shell_plus&lt;/code&gt; commands, it accepts and optional &lt;code&gt;--print-sql&lt;/code&gt; argument, which prints all the SQL queries that are being executed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;./manage.py&lt;span class="w"&gt; &lt;/span&gt;runserver_plus&lt;span class="w"&gt; &lt;/span&gt;--print-sql
./manage.py&lt;span class="w"&gt; &lt;/span&gt;shell_plus&lt;span class="w"&gt; &lt;/span&gt;--print-sql
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Whenever an SQL query gets executed, it prints the query and time taken for it in console.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_staff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;SELECT&lt;/span&gt; &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"last_login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_superuser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_staff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"date_joined"&lt;/span&gt;
  &lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;
 &lt;span class="n"&gt;WHERE&lt;/span&gt; &lt;span class="s2"&gt;"auth_user"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"is_staff"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
 &lt;span class="n"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;


&lt;span class="n"&gt;Execution&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.002107&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;QuerySet&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;anand&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chillar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Using django-querycount&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/django-querycount/"&gt;Django-querycount&lt;/a&gt; provides a middleware to show SQL query count and show duplicate queries on console.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;|&lt;/span&gt;------&lt;span class="p"&gt;|&lt;/span&gt;-----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;------------&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Type&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Database&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Reads&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;Writes&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;Totals&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Duplicates&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt;------&lt;span class="p"&gt;|&lt;/span&gt;-----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;------------&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;RESP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;default&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt;------&lt;span class="p"&gt;|&lt;/span&gt;-----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;----------&lt;span class="p"&gt;|&lt;/span&gt;------------&lt;span class="p"&gt;|&lt;/span&gt;
Total&lt;span class="w"&gt; &lt;/span&gt;queries:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.7738s


Repeated&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;times.
SELECT&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"django_session"&lt;/span&gt;.&lt;span class="s2"&gt;"session_key"&lt;/span&gt;,
&lt;span class="s2"&gt;"django_session"&lt;/span&gt;.&lt;span class="s2"&gt;"session_data"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"django_session"&lt;/span&gt;.&lt;span class="s2"&gt;"expire_date"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;FROM
&lt;span class="s2"&gt;"django_session"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;WHERE&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"django_session"&lt;/span&gt;.&lt;span class="s2"&gt;"session_key"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="s1"&gt;'dummy_key AND "django_session"."expire_date"&lt;/span&gt;
&lt;span class="s1"&gt;&amp;gt; '&lt;/span&gt;&lt;span class="m"&gt;2018&lt;/span&gt;-05-31T09:38:56.369469+00:00&lt;span class="err"&gt;'&lt;/span&gt;::timestamptz&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This package provides &lt;a href="https://github.com/bradmontgomery/django-querycount#settings"&gt;additional settings&lt;/a&gt; to customize output.&lt;/p&gt;
&lt;h4&gt;Django logging&lt;/h4&gt;
&lt;p&gt;Instead of using any 3rd party package, we can use &lt;code&gt;django.db.backends&lt;/code&gt; logger to print all the SQL queries.&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;django.db.backends&lt;/code&gt; to loggers list and set log level and handlers.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    &lt;span class="s1"&gt;'loggers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'django.db.backends'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'DEBUG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'handlers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'console'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In runserver console, we can see all SQL queries that are being executed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m m-Double"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"action_time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"content_type_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"object_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"object_repr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"action_flag"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"change_message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"last_login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"is_superuser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"is_staff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"date_joined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_content_type"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_content_type"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"app_label"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_content_type"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"model"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INNER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"user_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"auth_user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LEFT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OUTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_content_type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"content_type_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_content_type"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"user_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"django_admin_log"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="s"&gt;"action_time"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DESC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2018&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;HTTP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m m-Double"&gt;1.69&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;127.0.0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;47734&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These are few ways to log all SQL queries to console. We can also write a custom middleware for better logging of these queries and get some insights.&lt;/p&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2018/05/django-tips-tricks-log-sql-queries-to-console.html</guid><pubDate>Thu, 14 Jun 2018 15:51:21 GMT</pubDate></item><item><title>How To Deploy Django Channels To Production</title><link>https://avilpage.com/2018/05/deploying-scaling-django-channels.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;In this article, we will see how to deploy &lt;a href="https://pypi.org/project/channels/"&gt;django channels&lt;/a&gt; to production and how we can scale it to handle more load. We will be using nginx as proxy server, &lt;a href="https://pypi.org/project/daphne/"&gt;daphne&lt;/a&gt; as ASGI server, gunicorn as WSGI server and redis for channel back-end.&lt;/p&gt;
&lt;p&gt;Daphne can serve HTTP requests as well as WebSocket requests. For stability and performance, we will use uwsgi/gunicorn to serve HTTP requests and daphne to serve websocket requests.&lt;/p&gt;
&lt;p&gt;We will be using systemd to create and manage processes instead of depending on third party process managers like supervisor or circus. We will be using ansible for managing deployments. If you don't want to use ansible, you can just replace template variables in the following files with actual values.&lt;/p&gt;
&lt;h4&gt;Nginx Setup&lt;/h4&gt;
&lt;p&gt;Nginx will be routing requests to WSGI server and ASGI server based on URL. Here is nginx configuration for server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}:&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ssl_certificate&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ssl_certificate_key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;access_log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;access&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;error_log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;avilpage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_redirect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_http_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_read_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_redirect&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;server_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;project_root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;favicon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ico&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;project_root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;favicon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ico&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;robots&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;project_root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;robots&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;WSGI Server Setup&lt;/h4&gt;
&lt;p&gt;We will use gunicorn for wsgi server. We can run gunicorn with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;gunicorn&lt;span class="w"&gt; &lt;/span&gt;avilpage.wsgi&lt;span class="w"&gt; &lt;/span&gt;--bind&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0.0.0:8000&lt;span class="w"&gt; &lt;/span&gt;--log-level&lt;span class="w"&gt; &lt;/span&gt;error&lt;span class="w"&gt; &lt;/span&gt;--log-file&lt;span class="o"&gt;=&lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;--settings&lt;span class="w"&gt; &lt;/span&gt;avilpage.production_settings
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create a systemd unit file to make it as a service.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;gunicorn&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/run/gunicorn/pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;{{ project_root }}&lt;/span&gt;
&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"DJANGO_SETTINGS_MODULE={{ project_name }}.production_settings"&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;{{ venv_bin }}/gunicorn {{ project_name}}.wsgi --bind 0.0.0.0:8000 --log-level error --log-file=- --workers 5 --preload&lt;/span&gt;


&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s TERM $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-abort&lt;/span&gt;
&lt;span class="na"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;


&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Whenever server restarts, systemd will automatically start gunicorn service. We can also restart gunicorn manually with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;service&lt;span class="w"&gt; &lt;/span&gt;gunicorn&lt;span class="w"&gt; &lt;/span&gt;restart
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;ASGI Server Setup&lt;/h4&gt;
&lt;p&gt;We will use daphne for ASGI server and it can be started with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;daphne&lt;span class="w"&gt; &lt;/span&gt;avilpage.asgi:application&lt;span class="w"&gt; &lt;/span&gt;--bind&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0.0.0&lt;span class="w"&gt; &lt;/span&gt;--port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--verbosity&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can create a systemd unit file like the previous one to create a service.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;daphne daemon&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/run/daphne/pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;
&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;{{ project_root }}&lt;/span&gt;
&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"DJANGO_SETTINGS_MODULE={{ project_name }}.production_settings"&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;{{ venv_bin }}/daphne --bind 0.0.0.0 --port 9000 --verbosity 0 {{project_name}}.asgi:application&lt;/span&gt;
&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s TERM $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-abort&lt;/span&gt;
&lt;span class="na"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;


&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Deployment&lt;/h4&gt;
&lt;p&gt;Here is &lt;a href="https://github.com/ChillarAnand/eddie/blob/master/ubuntu/config/playbooks/django_setup.yml"&gt;an ansible playbook&lt;/a&gt; which is used to deploy these config files to our server. To run the playbook on server &lt;code&gt;avilpage.com&lt;/code&gt;, execute&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;avilpage.com,&lt;span class="w"&gt; &lt;/span&gt;django_setup.yml
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Scaling&lt;/h4&gt;
&lt;p&gt;Now that we have deployed channels to production, we can do performance test to see how our server performs under load.&lt;/p&gt;
&lt;p&gt;For WebSockets, we can use &lt;a href="https://www.npmjs.com/package/thor"&gt;Thor&lt;/a&gt; to run performance test.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;thor&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wss://avilpage.com/ws/books/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Our server is able to handle &lt;code&gt;100 requests per second&lt;/code&gt; with a &lt;code&gt;latency of 800ms&lt;/code&gt;. This is good enough for low traffic website.&lt;/p&gt;
&lt;p&gt;To improve performance, we can use unix sockets instead of rip/port for gunicorn and daphne. Also, daphne has support for multiprocessing using &lt;a href="https://avilpage.com/2018/05/deploying-scaling-django-channels.html"&gt;shared file descriptors&lt;/a&gt;. Unfortunately, it doesn't work as expected. As &lt;a href="https://github.com/django/daphne/issues/182#issuecomment-387507887"&gt;mentioned here&lt;/a&gt;, we can use systemd templates and spawn multiple daphne process.&lt;/p&gt;
&lt;p&gt;An alternate way is to use &lt;a href="https://pypi.org/project/uvicorn/"&gt;uvicorn&lt;/a&gt; to start multiple workers. Install uvicorn using pip&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;uvicorn
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Start uvicorn ASGI server with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;uvicorn&lt;span class="w"&gt; &lt;/span&gt;avilpage.asgi&lt;span class="w"&gt; &lt;/span&gt;--log-level&lt;span class="w"&gt; &lt;/span&gt;critical&lt;span class="w"&gt; &lt;/span&gt;--workers&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will spin up 4 workers which should be able to handle more load. If this performance is not sufficient, we have to setup a load balancer and spin up multiple servers(just like scaling any other web application).&lt;/p&gt;</description><category>devops</category><category>django</category><category>featured</category><category>python</category><guid>https://avilpage.com/2018/05/deploying-scaling-django-channels.html</guid><pubDate>Fri, 18 May 2018 15:51:21 GMT</pubDate></item><item><title>Reliable Way To Test External APIs Without Mocking</title><link>https://avilpage.com/2018/04/reliable-way-to-test-external-apis-without-mocking.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Let us write a function which retrieves user information from GitHub API.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;requests&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get_github_user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'https://api.github.com/users/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To test this function, we can write a test case to call the external API and check if it is returning valid data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_get_github_user_info&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ChillarAnand'&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_github_user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Even though this test case is reliable, this won't be efficient when we have many APIs to test as it sends unwanted requests to external API and makes tests slower due to I/O.&lt;/p&gt;
&lt;p&gt;A widely used solution to avoid external API calls is &lt;a href="https://en.wikipedia.org/wiki/Mock_object"&gt;mocking&lt;/a&gt;. Instead of getting the response from external API, use a mock object which returns similar data.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;unittest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_get_github_user_info_with_mock&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'requests.get'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mock_get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ChillarAnand'&lt;/span&gt;

        &lt;span class="n"&gt;mock_get&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;json_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;mock_get&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json_response&lt;/span&gt;

        &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_github_user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This solves above problems but creates additional problems.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unreliable. Even though test cases pass, we are not sure if API is up and is returning a valid response.&lt;/li&gt;
&lt;li&gt;Maintenance. We need to ensure mock responses are up to date with API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To avoid this, we can cache the responses using &lt;a href="https://pypi.python.org/pypi/requests-cache"&gt;requests-cache&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;requests_cache&lt;/span&gt;

&lt;span class="n"&gt;requests_cache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'github_cache'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_get_github_user_info_without_mock&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ChillarAnand'&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_github_user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When running tests from developer machine, it will call the API for the first time and uses the cached response for subsequent API calls. On CI pipeline, it will hit the external API as there won't be any cache.&lt;/p&gt;
&lt;p&gt;When the response from external API changes, we need to invalidate the cache. Even if we miss cache invalidation, test cases will fail in CI pipeline before going into production.&lt;/p&gt;</description><category>django</category><category>python</category><category>testing</category><guid>https://avilpage.com/2018/04/reliable-way-to-test-external-apis-without-mocking.html</guid><pubDate>Sun, 08 Apr 2018 15:51:21 GMT</pubDate></item><item><title>Convert Browser Requests To Python Requests For Scraping</title><link>https://avilpage.com/2018/03/convert-browser-requests-to-python-requests.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Scraping content behind a login page is bit difficult as there are wide variety of authentication mechanisms and web server needs correct headers, session, cookies to authenticate the request.&lt;/p&gt;
&lt;p&gt;If we need a crawler which runs everyday to scrape content, then we have to implement authentication mechanism. If we need to quickly scrape content just for once, implementing authentication is an overhead.&lt;/p&gt;
&lt;p&gt;Instead, we can manually login to the website, capture an authenticated request and use it for scraping other pages by changing url/form parameters.&lt;/p&gt;
&lt;p&gt;From browser developer options, we can capture &lt;a href="https://curl.haxx.se/"&gt;curl&lt;/a&gt; equivalent command for any request from &lt;code&gt;Network&lt;/code&gt; tab with &lt;code&gt;copy as cURL&lt;/code&gt; option.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/requests-python-browser.png" height="300px" width="600"&gt;
&lt;/p&gt;

&lt;p&gt;Here is one such request.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;curl&lt;/span&gt; &lt;span class="s1"&gt;'http://avilpage.com/dummy'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Cookie: ASPSESSIONIDSABAAQDA=FKOHHAGAFODIIGNNNDFKNGLM'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Origin: http://avilpage.com'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Accept-Encoding: gzip, deflate'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Accept-Language: en-US,en;q=0.9,ms;q=0.8,te;q=0.7'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Upgrade-Insecure-Requests: 1'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/x-www-form-urlencoded'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Cache-Control: max-age=0'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Referer: http://avilpage.com/'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'Connection: keep-alive'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="s1"&gt;'DNT: 1'&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="s1"&gt;'page=2&amp;amp;category=python'&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;compressed&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once we get curl command, we can directly convert it to python requests using &lt;a href="https://pypi.python.org/pypi/uncurl/"&gt;uncurl&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;uncurl
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since the copied curl request is in clipboard, we can pipe it to uncurl.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;clipit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;uncurl&lt;/span&gt;

&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://avilpage.com/dummy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'page=2&amp;amp;category=python'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Accept-Encoding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"gzip, deflate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Accept-Language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"en-US,en;q=0.9,ms;q=0.8,te;q=0.7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Cache-Control"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"max-age=0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"http://avilpage.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Referer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"http://avilpage.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Upgrade-Insecure-Requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"User-Agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"ASPSESSIONIDSABAAQDA"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"FKOHHAGAFODIIGNNNDFKNGLM"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we have to use some other programming language, we can use &lt;a href="https://curl.trillworks.com/"&gt;curlconverter&lt;/a&gt; to convert curl command to Go or Node.js equivalent code.&lt;/p&gt;
&lt;p&gt;Now, we can use this code to get contents of current page and then continue scraping from the urls in it.&lt;/p&gt;</description><category>python</category><category>scraping</category><guid>https://avilpage.com/2018/03/convert-browser-requests-to-python-requests.html</guid><pubDate>Mon, 26 Mar 2018 15:51:21 GMT</pubDate></item><item><title>Running Django Web Apps On Android Devices</title><link>https://avilpage.com/2018/02/deploy-django-web-app-android.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When deploying a django webapp to Linux servers, Nginx/Apache as server, PostgreSQL/MySQL as database are preferred. For this tutorial, we will be using django development server with SQLite database.&lt;/p&gt;
&lt;p&gt;First install &lt;a href="https://play.google.com/store/apps/details?id=berserker.android.apps.sshdroid"&gt;SSHDroid&lt;/a&gt; app on Android. It will start ssh server on port 2222. If android phone is rooted, we can run ssh on port 22.&lt;/p&gt;
&lt;p&gt;Now install &lt;a href="https://play.google.com/store/apps/details?id=org.qpython.qpy"&gt;QPython&lt;/a&gt;. This comes bundled with pip, which will install required python packages.&lt;/p&gt;
&lt;p&gt;Instead of installing these two apps, we can use &lt;a href="https://github.com/termux/termux-app/"&gt;Termux&lt;/a&gt;, &lt;a href="https://github.com/corbinlc/GNURootDebian"&gt;GNURoot Debian&lt;/a&gt; or some other app which provides Linux environment in Android. These apps will provide &lt;code&gt;apt&lt;/code&gt; package manager, which can install &lt;code&gt;python&lt;/code&gt; and &lt;code&gt;openssh-server&lt;/code&gt; packages.&lt;/p&gt;
&lt;p&gt;I have used &lt;a href="https://github.com/ChillarAnand/django-bookmarks"&gt;django-bookmarks&lt;/a&gt;, a simple CRUD app to test this setup. We can use rsync or adb shell to copy django project to android.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;rsync&lt;span class="w"&gt; &lt;/span&gt;-razP&lt;span class="w"&gt; &lt;/span&gt;django-bookmarks&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt;@&lt;span class="nv"&gt;$HOST&lt;/span&gt;:/data/local/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now ssh into android, install django and start django server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;@&lt;span class="nv"&gt;$HOST&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;django
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/data/local/django-bookmarks
$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;manage.py&lt;span class="w"&gt; &lt;/span&gt;runvserver
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will start development server on port 8000. To share this webapp with others, we will expose it with &lt;a href="https://serveo.net/"&gt;serveo&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;:localhost:8000&lt;span class="w"&gt; &lt;/span&gt;serveo.net

Forwarding&lt;span class="w"&gt; &lt;/span&gt;HTTP&lt;span class="w"&gt; &lt;/span&gt;traffic&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;https://incepro.serveo.net
Press&lt;span class="w"&gt; &lt;/span&gt;g&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;GUI&lt;span class="w"&gt; &lt;/span&gt;session&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;ctrl-c&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;quit.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can share our django app with anyone.&lt;/p&gt;
&lt;p&gt;I have used Moto G4 Plus phone to run this app. I have done a quick load test with Apache Bench.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ab&lt;span class="w"&gt; &lt;/span&gt;-k&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Accept-Encoding: gzip, deflate"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
http://incepro.serveo/list/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is able to server 15+ requests concurrently with an average response time of 800ms.&lt;/p&gt;
&lt;p&gt;We can write a simple shell script or ansible playbook to automate this deployment process and we can host a low traffic website on an android phone if required.&lt;/p&gt;</description><category>android</category><category>django</category><category>python</category><guid>https://avilpage.com/2018/02/deploy-django-web-app-android.html</guid><pubDate>Mon, 19 Feb 2018 12:10:56 GMT</pubDate></item><item><title>Load Testing Celery With Different Brokers</title><link>https://avilpage.com/2018/02/load-testing-celery-brokers.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Celery is mainly used to offload work from request/response cycle in web applications and to build pipelines in data processing applications. Lets run a load test on celery to see how well it queues the tasks with various brokers.&lt;/p&gt;
&lt;p&gt;Let us take a simple add task and measure queueing time.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;timeit&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;celery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Celery&lt;/span&gt;

&lt;span class="n"&gt;broker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'memory://'&lt;/span&gt;


&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Celery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;broker&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;


&lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;
&lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s2"&gt; tasks/sec"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On development machine, with AMD A4-5000 CPU, queueing time is as follows&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;memory ---&amp;gt; 400 tasks/sec&lt;/li&gt;
&lt;li&gt;rabbitmq ---&amp;gt; 300 tasks/sec&lt;/li&gt;
&lt;li&gt;redis ---&amp;gt; 250 tasks/sec&lt;/li&gt;
&lt;li&gt;postgres ---&amp;gt; 30 tasks/sec&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On production machine, with Intel(R) Xeon(R) CPU E5-2676, queueing time is as follows&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;memory ---&amp;gt; 2000 tasks/sec&lt;/li&gt;
&lt;li&gt;rabbitmq ---&amp;gt; 1400 tasks/sec&lt;/li&gt;
&lt;li&gt;redis ---&amp;gt; 1200 tasks/sec&lt;/li&gt;
&lt;li&gt;postgres ---&amp;gt; 200 tasks/sec&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For low/medium traffic webistes and applications, 1000 tasks/second should be fine. For high traffic webistes, there will be multiple servers queueing up the tasks.&lt;/p&gt;
&lt;p&gt;Incase if we need to queue the tasks at a higher rate and if we have task arguments before hand, we can chunk the tasks.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will divide 1000 tasks into 10 groups of 100 tasks each. As there is no messaging overhead, it can queue any number of tasks in less than a second.&lt;/p&gt;</description><category>celery</category><category>python</category><guid>https://avilpage.com/2018/02/load-testing-celery-brokers.html</guid><pubDate>Fri, 09 Feb 2018 13:49:18 GMT</pubDate></item><item><title>How To Plot Renko Charts With Python?</title><link>https://avilpage.com/2018/01/how-to-plot-renko-charts-with-python.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Renko"&gt;Renko charts&lt;/a&gt; are time independent and are efficient to trade as they eliminate noise. In this article we see how to plot renko charts of any instrument with OHLC data using Python.&lt;/p&gt;
&lt;p&gt;To plot renko charts, we can choose a fixed price as brick value or calculate it based on ATR(Average True Range) of the instrument.&lt;/p&gt;
&lt;p&gt;There are two types of Renko charts based on which bricks are calculated.&lt;/p&gt;
&lt;h4&gt;Renko chart - Price movement&lt;/h4&gt;
&lt;p&gt;First one is based on price movement. In this, we will divide the price movement of current duration by brick size to get the bricks.&lt;/p&gt;
&lt;p&gt;Once bricks are obtained, we need to assign the brick colors based on the direction of price movement and then plot rectangles for each available brick.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;matplotlib.patches&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;matplotlib.pyplot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;plt&lt;/span&gt;


&lt;span class="n"&gt;brick_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;plot_renko&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;brick_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;fig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gca&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;y_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;prev_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;bricks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;bricks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;bricks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bricks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;facecolor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'green'&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;facecolor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'red'&lt;/span&gt;

        &lt;span class="n"&gt;prev_num&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;

        &lt;span class="n"&gt;renko&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prev_num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;brick_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;brick_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;facecolor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;facecolor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renko&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'cdiff'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'close'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'close'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dropna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'bricks'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cdiff'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;brick_size&lt;/span&gt;

&lt;span class="n"&gt;bricks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'bricks'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'bricks'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;
&lt;span class="n"&gt;plot_renko&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bricks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;brick_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is a sample renko chart plotted using the above code.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/python-renko3.png"&gt;
&lt;/p&gt;

&lt;h4&gt;Renko chart - Period close&lt;/h4&gt;
&lt;p&gt;In this bricks are calculated based on the close price of the instrument. Calculation of bricks is sligtly complex compared to price movement chart. I have created a seperate package called &lt;a href="https://pypi.python.org/pypi/stocktrends"&gt;stocktrends&lt;/a&gt; which has this calculation.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;stocktrends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Renko&lt;/span&gt;

&lt;span class="n"&gt;renko&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Renko&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;renko&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;brick_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;renko&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_ohlc_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will give OHLC data for the renko chart. Now we can use this values to plot the charts as mentioned above.&lt;/p&gt;</description><category>python</category><category>technical-analysis</category><category>trading</category><guid>https://avilpage.com/2018/01/how-to-plot-renko-charts-with-python.html</guid><pubDate>Wed, 10 Jan 2018 09:27:23 GMT</pubDate></item><item><title>Automatic Magnetometer Calibration With Arduino</title><link>https://avilpage.com/2017/12/automatic-magnetometer-calibration-with-arduino.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;If we take readings from a 3-axis &lt;a href="https://en.wikipedia.org/wiki/Magnetometer"&gt;magnetometers&lt;/a&gt; like HMC5883L, AK8963C (used in MPU9250) or LSM303DLHC and plot them, its response should be a sphere with ceter at origin.&lt;/p&gt;
&lt;p&gt;In practice, due to the presence of hard and soft iron distortions, the response will be an ellipsiod with its center shifted away from origin. We need to calibrate the magnetometer to nullify the distortions.&lt;/p&gt;
&lt;p&gt;First we need to get sample readings of magnetometer in various positions. Depending on the magnetometer, we need to connect it to arduino and take readings by rotating it in 8 shape.&lt;/p&gt;
&lt;h4&gt;Calibration&lt;/h4&gt;
&lt;p&gt;Hard iron biases shifts center away from origin. We can eliminate this error by calculating the offsets and shifting the readings.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_calibrated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_calibrated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_calibrated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// get min/max values by taking readings&lt;/span&gt;
&lt;span class="c1"&gt;// from magnetometer of your choice&lt;/span&gt;

&lt;span class="n"&gt;mx_offset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mx_min&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;my_offset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_min&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mz_offset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mz_min&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;mx_calibrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;my_calibrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mz_calibrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Soft iron biases makes the axial responses uneven which results in ellipsiod shape. An easier way to correct this is to rescale the axial readings to an average value.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_scale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;mx_scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mx_max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;my_scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mz_scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mz_max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;avg_scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mx_scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;mx_calibrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;avg_scale&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mx_offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;my_calibrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;avg_scale&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;mz_calibrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;avg_scale&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mz_offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can caclulate these biases once and store them in our code so that we don't need to calibrate it everytime. We can also write an auto update function which will recalibrate offsets &amp;amp; scale for every new reading.&lt;/p&gt;</description><category>arduino</category><category>how-to</category><guid>https://avilpage.com/2017/12/automatic-magnetometer-calibration-with-arduino.html</guid><pubDate>Sat, 02 Dec 2017 21:21:21 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #9 - Auto Register Models In Admin</title><link>https://avilpage.com/2017/11/django-tricks-auto-register-models-admin.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Inbuilt &lt;a href="https://docs.djangoproject.com/en/1.11/ref/contrib/admin/"&gt;admin interface&lt;/a&gt; is one the most powerful &amp;amp; popular feature of Django. Once we create the models, we need to register them with admin, so that it can read metadata and populate interface for it.&lt;/p&gt;
&lt;p&gt;If the django project has too many models or if it has a legacy database, then adding all those models to admin becomes a tedious task. To automate this process, we can programatically fetch all the models in the project and register them with admin.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.apps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;


&lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_models&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This works well if we are just auto registering all the models. However if we try some customisations and try to register them in &lt;code&gt;admin.py&lt;/code&gt; files in our apps, there will be conflicts as Django doesn't allow registering the same model twice.&lt;/p&gt;
&lt;p&gt;So, we need to make sure this piece of code runs after all &lt;code&gt;admin.py&lt;/code&gt; files are loaded and it should ignore models which are already registered. We can safely hook this code in appconfig.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.apps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AppConfig&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;CustomApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppConfig&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_models&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sites&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlreadyRegistered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now all models will get registed automatically. If we go to a model page in admin, it will just show 1 column like this.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-admin-auto.png" width="600px"&gt;
&lt;/p&gt;

&lt;p&gt;This is not informative for the users who want to see the data. We can create a &lt;code&gt;ListAdminMixin&lt;/code&gt;,  which will populate &lt;code&gt;list_display&lt;/code&gt; with all the fields in the model. We can create a new admin class which will subclass &lt;code&gt;ListAdminMixin&lt;/code&gt; &amp;amp; &lt;code&gt;ModelAdmin&lt;/code&gt;. We can use this admin class when we are registering the model so that all the fields in the model will show up in the admin.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.apps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AppConfig&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ListAdminMixin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin_site&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListAdminMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin_site&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;CustomApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppConfig&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_models&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;admin_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AdminClass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListAdminMixin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin_class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sites&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlreadyRegistered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now whenever we create a new model or add a new field to an existing model, it will get reflected in the admin automatically.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-admin-auto-2.png" width="600px"&gt;
&lt;/p&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2017/11/django-tricks-auto-register-models-admin.html</guid><pubDate>Fri, 24 Nov 2017 21:21:21 GMT</pubDate></item><item><title>How To Install Custom ROMs In Xiamo MiPad?</title><link>https://avilpage.com/2017/11/how-to-install-custom-roms-in-mipad.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Mi Pad and other Xiamo devices has Mi UI OS which is a dual boot system. A major problem with this system is it has only ~600 MB of space in 1st partition. Because of this, we cannot install some custom ROMs as they need more space. In this article we will see how to merge both partitions to get more free space and install any custom ROM.&lt;/p&gt;
&lt;h3&gt;Install TWRP&lt;/h3&gt;
&lt;p&gt;Dowload latest recovery from &lt;a href="https://twrp.me/"&gt;twrp.me&lt;/a&gt;. Copy it to android device or push it to android using adb.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;adb&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;twrp-3.1.1-0-mocha.img&lt;span class="w"&gt; &lt;/span&gt;/sdcard/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now put the device into fastboot mode by pressing &lt;strong&gt;Volume down&lt;/strong&gt; &amp;amp; &lt;strong&gt;Power&lt;/strong&gt; button simultanesouly when you switch it on. When in fastboot mode, flash the downloaded recovery file&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;fastboot&lt;span class="w"&gt; &lt;/span&gt;flash&lt;span class="w"&gt; &lt;/span&gt;recovery&lt;span class="w"&gt; &lt;/span&gt;twrp-3.1.1-0-mocha.img
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can go to recovery mode using adb.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;adb reboot recovery
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Merge partitions&lt;/h3&gt;
&lt;p&gt;Before installing custom ROM, we need to merge partitions so that we will have enough space to install ROM. If you are familiar with &lt;a href="https://www.gnu.org/software/parted/"&gt;parted&lt;/a&gt; command, you can directly merge the partitions from terminal in TWRP recovery.&lt;/p&gt;
&lt;p&gt;There is also a script which you can flash to do the partition. You can read &lt;a href="http://en.miui.com/thread-118294-1-1.html"&gt;this guide&lt;/a&gt; on mi forum for more information.&lt;/p&gt;
&lt;p&gt;After partition is completed, from TWRP go to &lt;strong&gt;Wipe&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Advanced wipe&lt;/strong&gt; -&amp;gt; Select &lt;strong&gt;System&lt;/strong&gt; -&amp;gt; Click on &lt;strong&gt;Repair or change file system&lt;/strong&gt;. Here it should show that free space in system is more than 1GB.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/xiamo-mipad-custom-rom.jpg" width="600" height="400"&gt;
&lt;/p&gt;

&lt;h3&gt;Install ROM&lt;/h3&gt;
&lt;p&gt;After partitions are merged, it is straight forward to install any custom ROM. Download a custom ROM like lineage or RR, push it to device and then install it from TWRP. After reboot, you will see the custom ROM booting.&lt;/p&gt;</description><category>android</category><guid>https://avilpage.com/2017/11/how-to-install-custom-roms-in-mipad.html</guid><pubDate>Sun, 19 Nov 2017 10:39:27 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #8 - Hyperlink Foreignkey Fields In Admin</title><link>https://avilpage.com/2017/11/django-tips-tricks-hyperlink-foreignkey-admin.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Consider &lt;code&gt;Book&lt;/code&gt; model which has &lt;code&gt;Author&lt;/code&gt; as foreignkey.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can register these models with admin interface as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;.models&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Book&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;BookAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;list_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BookAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once they are registed, admin page shows &lt;code&gt;Book&lt;/code&gt; model like this.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-tips-tricks-1.png"&gt;
&lt;/p&gt;

&lt;p&gt;While browsing books, we can see &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;author&lt;/code&gt;. Here, name field is liked to change view of book. But author field is shown as plain text. If we have to modify author name, we have to go back to authors admin page, search for relevant author and then change name.&lt;/p&gt;
&lt;p&gt;This becomes tedious if we spend lot of time in admin for tasks like this. Instead, if author field is hyperlinked to its change view, we can directly go to that page.&lt;/p&gt;
&lt;p&gt;Django provides an option to &lt;a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#reversing-admin-urls"&gt;access admin views by its URL reversing system&lt;/a&gt;. For example, we can get change view of author model in book app using &lt;code&gt;reverse("admin:book_author_change", args=id)&lt;/code&gt;. Now we can use this url to hyperlink author field in book admin.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.contrib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.utils.safestring&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mark_safe&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;BookAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;list_display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'author_link'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;author_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"admin:book_author_change"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;a href="&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/a&amp;gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mark_safe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;author_link&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;short_description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Author'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now in the book admin view, author field will be hyperlinked to its change view and we can visit just by clicking it.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/django-tips-tricks-2.png"&gt;
&lt;/p&gt;

&lt;p&gt;Depending on requirements, we can link any field in django to other fields or add custom fields to improve productivity.&lt;/p&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2017/11/django-tips-tricks-hyperlink-foreignkey-admin.html</guid><pubDate>Tue, 14 Nov 2017 21:21:21 GMT</pubDate></item><item><title>Remove Clock From LockScreen/StatusBar On Android RR</title><link>https://avilpage.com/2017/11/how-to-remove-clock-lock-screen-status-bar.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Last year, I wrote a blog post on &lt;a href="https://avilpage.com/2016/09/remove-clock-lock-screen-status-bar-android.html"&gt;how to remove clock from lock screen and status bar&lt;/a&gt; if &lt;a href="http://repo.xposed.info/module/de.robv.android.xposed.installer"&gt;xposed&lt;/a&gt; is installed on your android device. You can also do this without xposed if you are using RR(Resurrection Remix) as it comes with a lot of inbuilt customization.&lt;/p&gt;
&lt;h4&gt;Remove Clock From LockScreen&lt;/h4&gt;
&lt;p&gt;To remove clock from lockscreen, go to &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Configurations&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Lock screen&lt;/strong&gt; -&amp;gt;  &lt;strong&gt;Show lock screen lock&lt;/strong&gt;.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_11.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_12.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_13.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;h4&gt;Remove Time From StatusBar&lt;/h4&gt;
&lt;p&gt;To remove clock from status bar, go to &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Configurations&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Status bar&lt;/strong&gt; -&amp;gt;  &lt;strong&gt;System UI tuner&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Time&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Dont show this icon&lt;/strong&gt;.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_11.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_14.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_15.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p&gt;Once you do this, you will have a clean lockscreen and statusbar without any date or time them.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/remove_clock_android_16.jpg" height="400px" width="220"&gt;
&lt;/p&gt;</description><category>android</category><category>how-to</category><guid>https://avilpage.com/2017/11/how-to-remove-clock-lock-screen-status-bar.html</guid><pubDate>Mon, 13 Nov 2017 20:24:38 GMT</pubDate></item><item><title>Bluetooth Serial Communication Between Linux &amp; Android</title><link>https://avilpage.com/2017/10/bluetooth-communication-between-ubuntu-android.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Most laptops and smart phones(Android/iPhone) have builtin Bluetooth modules. We can use this bluetooth module to communicate with other devices or with other bluetooth modules like HC-05 or HM-10.&lt;/p&gt;
&lt;p&gt;In this article, we will learn how to send data between laptop and android bluetooth.&lt;/p&gt;
&lt;p&gt;First, we need to pair with a bluetooth device to send information. From Ubuntu, we can pair to a Bluetooth device from Bluetooth settings. Alternatively, we can also use CLI to do the same.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bluetoothctl&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Controller&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;D7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;AC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;asus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;94&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;E9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;BB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;F8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DESKTOP&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;C4ECO3K&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;athene&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;94&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nl"&gt;D&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nl"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OnePlus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;A5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;61&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;D5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Lenovo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VIBE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;K5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Plus&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;AC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;C3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nl"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;A0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;CE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;EF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Galaxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;J2&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;D3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HC&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;power&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="n"&gt;Changing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;power&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;succeeded&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;registered&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;
&lt;span class="k"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;successful&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="n"&gt;Discovery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CHG&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Controller&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nl"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;D7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;AC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Discovering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CHG&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;94&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;E9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;BB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;F8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;RSSI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CHG&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;RSSI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;66&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bluetooth&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;
&lt;span class="n"&gt;Attempting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CHG&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;E&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nl"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nl"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Paired&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="n"&gt;Pairing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;successful&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To communicate with paired devices, we will use &lt;a href="https://en.wikipedia.org/wiki/List_of_Bluetooth_protocols"&gt;RFCOMM protocol&lt;/a&gt;. RFCOMM is just a serial port emulation and provides reliable data tranfer like TCP.&lt;/p&gt;
&lt;p&gt;From ubuntu, lets open a port for communication.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;rfcomm&lt;span class="w"&gt; &lt;/span&gt;listen&lt;span class="w"&gt; &lt;/span&gt;/dev/rfcomm0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From Android, we have to connect to ubuntu. For this, we can use &lt;a href="https://play.google.com/store/apps/details?id=com.hardcodedjoy.roboremofree&amp;amp;hl=en"&gt;Roboremo&lt;/a&gt; app which supports RFCOMM.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;rfcomm&lt;span class="w"&gt; &lt;/span&gt;listen&lt;span class="w"&gt; &lt;/span&gt;/dev/rfcomm0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
Waiting&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;connection&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;channel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
Connection&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;88&lt;/span&gt;:79:7E:7B:4C:87&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;/dev/rfcomm0
Press&lt;span class="w"&gt; &lt;/span&gt;CTRL-C&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;hangup
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the connection is established, we can communicate between devices.&lt;/p&gt;
&lt;p&gt;In Unix like systems, OS provides a device file as an interface for device driver. To send and read messages from Linux or Mac is as easy as reading and writing to a file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# to send message to bluetooth&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'hello from ubuntu'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/rfcomm0
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can see the received messages on Android&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/arduino-ubuntu-bluetooth.jpg"&gt;
&lt;/p&gt;

&lt;p&gt;We can also send messages from android and read from ubuntu.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# to read messages from bluetooth&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/dev/rfcomm0
hello&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;android
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way, we can communicate with any bluetooth module using a laptop or a smart phone.&lt;/p&gt;</description><category>android</category><category>bluetooth</category><category>command-line</category><category>linux</category><guid>https://avilpage.com/2017/10/bluetooth-communication-between-ubuntu-android.html</guid><pubDate>Tue, 03 Oct 2017 14:53:04 GMT</pubDate></item><item><title>Arduino Programming From Text Editor &amp; Command Line</title><link>https://avilpage.com/2017/08/arduino-programming-from-text-editor-cli.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;To program Arduino, we can use &lt;a href="https://www.arduino.cc/en/main/software"&gt;Arduino IDE&lt;/a&gt; which facilitates writing and uploading code to the board.&lt;/p&gt;
&lt;p&gt;If we are using a text editor for programming, it will have lot of customisations which speed up development process. In such case, it is better to use same text editor for arduino programming too.&lt;/p&gt;
&lt;p&gt;I use Emacs as IDE and there is &lt;a href="https://github.com/bookest/arduino-mode"&gt;arduino mode&lt;/a&gt; for emacs which provides syntax highlighting and some useful utilites to write arduino code. We can find such packages for other editors also.&lt;/p&gt;
&lt;p&gt;Arduino also provides cli interface to upload code to arduino. To upload code, we need to specify port, board and the code to upload.&lt;/p&gt;
&lt;p&gt;In Linux system, to upload a file called &lt;code&gt;foo.ino&lt;/code&gt;, we can run&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;arduino&lt;span class="w"&gt; &lt;/span&gt;--port&lt;span class="w"&gt; &lt;/span&gt;/dev/ttyACM0&lt;span class="w"&gt; &lt;/span&gt;--board&lt;span class="w"&gt; &lt;/span&gt;arduino:avr:mega
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;--upload&lt;span class="w"&gt; &lt;/span&gt;foo.ino
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;An alternate way is to use &lt;a href="https://github.com/platformio/platformio-core/"&gt;platformio&lt;/a&gt;, an opensource tool chain for IoT development.&lt;/p&gt;
&lt;p&gt;It can be installed using pip.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;platformio
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once it is installed, code can be directly uploaded using &lt;code&gt;ci&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pio&lt;span class="w"&gt; &lt;/span&gt;ci&lt;span class="w"&gt; &lt;/span&gt;--board&lt;span class="o"&gt;=&lt;/span&gt;megaatmega2560&lt;span class="w"&gt; &lt;/span&gt;--project-option&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"upload_port=/dev/ttyACM0"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--project-option&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"targets=upload"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;foo.ino
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By this we can use text editor to write code and arduino/platformio to upload code to arduino board.&lt;/p&gt;</description><category>arduino</category><category>command-line</category><guid>https://avilpage.com/2017/08/arduino-programming-from-text-editor-cli.html</guid><pubDate>Thu, 24 Aug 2017 13:29:59 GMT</pubDate></item><item><title>Using LSTM-CTC For Complex Script Recognition</title><link>https://avilpage.com/2017/07/using-lstm-ctc-for-complex-script-recognistion.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Most Indian languages have strong consonant-vowel structures which combine to give syllables. These syllables are written as one continuous ligature and they require &lt;a href="https://en.wikipedia.org/wiki/Complex_text_layout"&gt;complex text rendering&lt;/a&gt; (CTL) for type setting.&lt;/p&gt;
&lt;p&gt;Writing OCR (Optical Character Recognition) software for CTL scripts is a challenging task as segmentation is hard. Because of this overall accuracy drops drastically.&lt;/p&gt;
&lt;p&gt;A better approach is to use Connectionist Temporal Classification&lt;sup id="fnref:ctc"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2017/07/using-lstm-ctc-for-complex-script-recognistion.html#fn:ctc"&gt;1&lt;/a&gt;&lt;/sup&gt;(CTC) which can identify unsegmented sequence directly as it has a one-to-one correspondence between input samples and output labels.&lt;/p&gt;
&lt;p&gt;Here is a sample input and output of an &lt;a href="https://github.com/rakeshvar/rnn_ctc"&gt;RNN-CTC&lt;/a&gt; network which takes an unsegmented sequence and outputs labels.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/ctc.png"&gt;
&lt;/p&gt;

&lt;p&gt;Open-source OCR software &lt;a href="https://github.com/tmbdev/ocropy/"&gt;ocorpy&lt;/a&gt; uses BLSTM-CTC for text recognition. &lt;a href="https://github.com/tesseract-ocr/tesseract"&gt;Tesseract&lt;/a&gt; started using the same in its latest(4.0) version.&lt;/p&gt;
&lt;p&gt;I have &lt;a href="https://github.com/ChillarAnand/likitham"&gt;trained a model&lt;/a&gt; to recognize Telugu script using Ocropy and the accuracy is ~99% which is far better when compared to OCR software without CTC which are accurate to ~70%.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:ctc"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Connectionist_temporal_classification"&gt;https://en.wikipedia.org/wiki/Connectionist_temporal_classification&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2017/07/using-lstm-ctc-for-complex-script-recognistion.html#fnref:ctc" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>artificial-intelligence</category><category>data-science</category><category>python</category><guid>https://avilpage.com/2017/07/using-lstm-ctc-for-complex-script-recognistion.html</guid><pubDate>Sat, 22 Jul 2017 14:09:32 GMT</pubDate></item><item><title>Auto Register Subclasses Without Metaclass in Python</title><link>https://avilpage.com/2017/06/auto-register-subclasess-without-metaclass.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;In registry pattern, a &lt;code&gt;registry&lt;/code&gt; maintains global association from keys to objects, so that objects can be reached from anywhere by simple identifier. This is useful for doing reverse lookups.&lt;/p&gt;
&lt;p&gt;When building a registry, programmers have to explicitly register each object with registry. Manually building a registry is error prone and it is tedious if there are too many objects to register. It is better to auto register objects if possible.&lt;/p&gt;
&lt;p&gt;A commonly used approach is to use inheritance as an organizing mechanism. Create &lt;a href="https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Metaprogramming.html#example-self-registration-of-subclasses"&gt;a meta class which will auto register&lt;/a&gt; classes and then create base class with this meta class.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;REGISTRY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;register_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_class&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;REGISTRY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target_class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_class&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;MetaRegistry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;register_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;BaseClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metaclass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MetaRegistry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseClass&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseClass&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now whenever you subclass &lt;code&gt;BaseClass&lt;/code&gt;, it gets registered in the global registry. In the above example, &lt;code&gt;Foo&lt;/code&gt;, &lt;code&gt;Bar&lt;/code&gt; gets registered automatically.&lt;/p&gt;
&lt;p&gt;Eventhough it solves registration problem, it is hard to understand the code unless you know how metaclasses work.&lt;/p&gt;
&lt;p&gt;A simple alternative for this is to use &lt;code&gt;__subclasses__()&lt;/code&gt; to get subclasess and register them.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;REGISTRY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;BaseClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__subclasses__&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will work only for direct subclasses and won't with indirect subclasses like this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Baz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To solve this, we can use a function to recursively retrieve all subclasses of a class.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;subclasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;registry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;subs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__subclasses__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;subclasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt;


&lt;span class="n"&gt;REGISTRY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;subclasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseClass&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0487/"&gt;PEP 487&lt;/a&gt; provides &lt;code&gt;__init_subclass__&lt;/code&gt; hook in class body  to customize class creation without the use of metaclass. We can our registration logic in this &lt;code&gt;__init_subclass__&lt;/code&gt; hook.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;BaseClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;__init_subclass__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;register_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init_subclass__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is available only in Python 3.6+. For older versions, we have to use the recursive function to get all subclasess. This code is easier to understand than metaclass example.&lt;/p&gt;</description><category>python</category><guid>https://avilpage.com/2017/06/auto-register-subclasess-without-metaclass.html</guid><pubDate>Sat, 10 Jun 2017 15:30:27 GMT</pubDate></item><item><title>How To Auto Reload Celery Workers In Development?</title><link>https://avilpage.com/2017/05/how-to-auto-reload-celery-workers-in-development.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;We can pass &lt;code&gt;--autoreload&lt;/code&gt; option when starting celery worker. This will restart worker when codebase changes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;celery&lt;span class="w"&gt; &lt;/span&gt;worker&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;foo&lt;span class="w"&gt; &lt;/span&gt;--autoreload
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, it doesn't work as expected and &lt;a href="https://github.com/celery/celery/issues/1658"&gt;it is deprecated&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During development, we will keep on changing the code base. Manually restarting  celery worker everytime is a tedious process. It would be handy if workers can be auto reloaded whenever there is a change in the codebase.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://pypi.python.org/pypi/watchdog"&gt;Watchdog&lt;/a&gt; provides Python API and shell utilities to monitor file system events. We can install it with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;watchdog
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Watchdog provides &lt;code&gt;watchmedo&lt;/code&gt; a shell utilitiy to perform actions based on file events. It has &lt;code&gt;auto-restart&lt;/code&gt; subcommand to start a long-running subprocess and restart it. So, celery workers can be auto restarted using this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;watchmedo&lt;span class="w"&gt; &lt;/span&gt;auto-restart&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;celery&lt;span class="w"&gt; &lt;/span&gt;worker&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;foo
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default it will watch for all files in current directory. These can be changed by passing corresponding parameters.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;watchmedo&lt;span class="w"&gt; &lt;/span&gt;auto-restart&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*.py'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="w"&gt; &lt;/span&gt;celery&lt;span class="w"&gt; &lt;/span&gt;worker&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;foo
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you are using django and don't want to depend on watchdog, there is a simple trick to achieve this. Django has autoreload utility which is used by &lt;code&gt;runserver&lt;/code&gt; to restart WSGI server when code changes.&lt;/p&gt;
&lt;p&gt;The same functionality can be used to reload celery workers. Create a seperate management command called &lt;code&gt;celery&lt;/code&gt;. Write a function to kill existing worker and start new worker. Now hook this function to autoreload as follows.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;shlex&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;subprocess&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.core.management.base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseCommand&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django.utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;autoreload&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;restart_celery&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'pkill -9 celery'&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shlex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'celery worker -l info -A foo'&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shlex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Starting celery worker with autoreload...'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;autoreload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;restart_celery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can run celery worker with &lt;code&gt;python manage.py celery&lt;/code&gt; which will start a celery worker and autoreload it when codebase changes.&lt;/p&gt;</description><category>automation</category><category>celery</category><category>python</category><guid>https://avilpage.com/2017/05/how-to-auto-reload-celery-workers-in-development.html</guid><pubDate>Sun, 07 May 2017 04:22:47 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #7 - Django Auth Plugin For HTTPie</title><link>https://avilpage.com/2017/04/django-auth-plugin-for-httpie.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;a href="https://pypi.python.org/pypi/httpie"&gt;HTTPie&lt;/a&gt; is an alternative to curl for interacting with web services from CLI. It provides a simple and intuitive interface and it is handy to send arbitrary HTTP requests while testing/debugging APIs.&lt;/p&gt;
&lt;p&gt;When working with web applications that require authentication, using httpie is  difficult as authentication mechanism will be different for different applications. httpie has in built support for &lt;code&gt;basic&lt;/code&gt; &amp;amp; &lt;code&gt;digest&lt;/code&gt; authentication.&lt;/p&gt;
&lt;p&gt;To authenticate with Django apps, a user needs to make a &lt;code&gt;GET&lt;/code&gt; request to login page. Django sends login form with a CSRF token. User can submit this form with valid credentials and a session will be initiated.&lt;/p&gt;
&lt;p&gt;Establish session manually is boring and it gets tedious when working with multiple apps in multiple environments(development, staging, production).&lt;/p&gt;
&lt;p&gt;I have written a plugin called &lt;a href="https://pypi.python.org/pypi/httpie-django-auth"&gt;httpie-django-auth&lt;/a&gt; which automates django authentication. It can be installed with pip&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;httpie-django-auth
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, it uses &lt;code&gt;/admin/login&lt;/code&gt; to login. If you need to use some other URL for logging, set &lt;code&gt;HTTPIE_DJANGO_AUTH_URL&lt;/code&gt; environment variable.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;HTTPIE_DJANGO_AUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/accounts/login/'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can send authenticated requests to any URL as&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;http&lt;span class="w"&gt; &lt;/span&gt;:8000/profile&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="o"&gt;=&lt;/span&gt;django&lt;span class="w"&gt; &lt;/span&gt;--auth&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'username:password'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2017/04/django-auth-plugin-for-httpie.html</guid><pubDate>Thu, 20 Apr 2017 15:00:28 GMT</pubDate></item><item><title>Super Charge Your Shell For Python Development</title><link>https://avilpage.com/2017/03/super-charge-your-shell-for-python-development.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Last month, I gave a lightning talk about supercharging your shell for python development at &lt;a href="http://www.meetup.com/BangPypers/"&gt;BangPypers meetup&lt;/a&gt;.&lt;/p&gt;
&lt;iframe width="600" height="350" src="https://www.youtube.com/embed/lvmJ0tWCjFA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;This is a detailed blog post on how to setup your laptop for the same.&lt;/p&gt;
&lt;h3&gt;Autojump&lt;/h3&gt;
&lt;p&gt;When working on terminal, &lt;code&gt;cd&lt;/code&gt; is used to traverse directories.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/projects/python/django
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; is inefficient to quickly traverse directories which are in different paths and far away from each other.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/lib/elasticsearch/
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/sandbox/channels/demo
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;z&lt;/code&gt;, a oh-my-zsh plugin is efficient for traversing directories. With &lt;code&gt;z&lt;/code&gt;, directory can be changed by typing name of directory.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;z&lt;span class="w"&gt; &lt;/span&gt;junction
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of full name, just a substring would do.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;z&lt;span class="w"&gt; &lt;/span&gt;ju
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;z&lt;/code&gt; keeps a score of all visited directories and moves to most frecency(frequent+recent) directory that matches the substring.&lt;/p&gt;
&lt;p&gt;To install &lt;code&gt;z&lt;/code&gt;, install &lt;a href="https://avilpage.com/2015/03/install-oh-my-zsh-on-ubuntu.html"&gt;oh-my-zsh&lt;/a&gt; and add &lt;code&gt;z&lt;/code&gt; to plugins in &lt;code&gt;.zshrc&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;z&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Aliases&lt;/h3&gt;
&lt;p&gt;Read this old blog post on how &lt;a href="https://avilpage.com/2014/10/useful-shell-aliases-for-python-and.html"&gt;aliases will improve your productivity&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Autoenv&lt;/h3&gt;
&lt;p&gt;When working on multiple projects, it becomes necessary to use virtualenvs so that multiple versions of same package can be used. In addition to that, it be necessary to set environment variables on a per project basis.&lt;/p&gt;
&lt;p&gt;To automate all these things, &lt;a href="https://pypi.python.org/pypi/autoenv/"&gt;autoenv&lt;/a&gt; provides directory based environments. Whenever user changes directory, it will help to automatically activate environment and set environment variables.&lt;/p&gt;
&lt;p&gt;If you have file named &lt;code&gt;.env&lt;/code&gt; in a directory, autoenv will automatically source that file whenever user enters into it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;autoenv&lt;/code&gt; is a python package. It can be installed with&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;autoenv
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It provides a shell script which needs to sourced.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"source `which activate.sh`"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;~/.bashrc
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can create a .env file like this in project root.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/.virtualenvs/exp/bin/activate
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;foobar
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next time, when your enter into that directory, &lt;code&gt;autoenv&lt;/code&gt; finds &lt;code&gt;.env&lt;/code&gt; file and it will source it automatically.&lt;/p&gt;
&lt;h3&gt;Autoreload&lt;/h3&gt;
&lt;p&gt;I have written a sepeate blog post on how to &lt;a href="https://avilpage.com/2014/11/python-automagically-reload-imports-in.html"&gt;automagically reload imports&lt;/a&gt; long time back.&lt;/p&gt;
&lt;h3&gt;Autoimports&lt;/h3&gt;
&lt;p&gt;When you copy code and paste it in ipython interpreter, it might fail with &lt;code&gt;ImportError&lt;/code&gt; if required modules aren't already imported by the interpreter.&lt;/p&gt;
&lt;p&gt;Also when playing with code, having some predefined data would be handy. This avoids populating of data everytime shell starts.&lt;/p&gt;
&lt;p&gt;You can write an init script which will do all these things and load it automatically when ipython starts.&lt;/p&gt;
&lt;p&gt;Here is a &lt;a href="https://github.com/ChillarAnand/01/blob/master/python/ipython_config.py"&gt;simple init script&lt;/a&gt; which I use to auto import modules and data. This file can be auto loaded by specifying it in your config file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteractiveShellApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ipython_init.py'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Autocall&lt;/h3&gt;
&lt;p&gt;When using python interpreter, to call a function, you have to type parenthesis.Typing parenthesis is not ergonomic as you have to move both hands far away from homerow.&lt;/p&gt;
&lt;p&gt;IPython provides &lt;code&gt;autocall&lt;/code&gt; option to make functions callable without typing parenthesis. This can be activate with &lt;code&gt;%autocall&lt;/code&gt; magic.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;autocall&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;Automatic&lt;/span&gt; &lt;span class="n"&gt;calling&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Smart&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now functions can be called without parenthesis.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;------&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also enable this by default by activating it in ipython config file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteractiveShellApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;%a&lt;/span&gt;&lt;span class="s1"&gt;utocall  1'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These are some tips to become more productive with your shell when working on python projects.&lt;/p&gt;</description><category>command-line</category><category>python</category><guid>https://avilpage.com/2017/03/super-charge-your-shell-for-python-development.html</guid><pubDate>Sun, 26 Mar 2017 02:40:31 GMT</pubDate></item><item><title>Provisioning Laptop(s) With Ansible</title><link>https://avilpage.com/2017/03/provisioning-laptop-ansible.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Setting up a new laptop manually takes a lot of time and there is a good chance of forgetting tweaks made to configuration files. It is good idea to automate it via a shell script or using configuration management tools like Ansible. It also makes easy to sync configuration across multiple systems.&lt;/p&gt;
&lt;h3&gt;Why Ansible?&lt;/h3&gt;
&lt;p&gt;Ansible is lightweight and provides only a thin layer of abstraction. It connects to hosts via ssh and pushes changes. So, there is no need to setup anything on remote hosts.&lt;/p&gt;
&lt;h3&gt;Writing A Playbook&lt;/h3&gt;
&lt;p&gt;You should check out Ansible documentation to get familiar with ansible and &lt;a href="https://docs.ansible.com/ansible/playbooks.html"&gt;writing playbooks&lt;/a&gt;. Ansible uses yaml format for playbooks and it's human readable. Here is a simple playbook to install redis on ubuntu server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;
&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;

&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;update_cache&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ChillarAnand/01/blob/master/ubuntu/config/playbooks/ubuntu.yml"&gt;a playbook&lt;/a&gt; which I use to configure my laptop. As the playbook needs to run locally, just run&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ansible-playbook laptop-setup.yml -i localhost, -c local
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Bootstrap Script&lt;/h3&gt;
&lt;p&gt;To automate provisioning, a bootstrap script is required to make sure python, ansible are installed, to download and execute playbook on the system.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo apt update --yes
sudo apt install --yes python python-pip

sudo apt install --yes libssl-dev
sudo -H pip install ansible

wget -c https://path/to/playbook.yml

sudo ansible-playbook setup.yml -i localhost, -c local
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, to provision a laptop, just run the bootstrap script.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sh -c "$(wget https://path/to/bootstrap_script.sh"
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can use a git repo to track changes in playbook and bootstrap script. If you are using multiple laptops, running bootstrap script on them will make sure everything is synced across them.&lt;/p&gt;</description><category>automation</category><category>linux</category><guid>https://avilpage.com/2017/03/provisioning-laptop-ansible.html</guid><pubDate>Sat, 11 Mar 2017 14:16:32 GMT</pubDate></item><item><title>How BMTC Is Exploiting Crores From Bangalore Citizens?</title><link>https://avilpage.com/2017/02/bmtc-exploiting-crores-from-bangalore-citizens.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;a href="http://mybmtc.com" target="_blank"&gt;BMTC&lt;/a&gt; (Bengaluru Metropolitan Transport Corporation) is a government agency which operates the public transport bus service in Bangalore, India. It holds monopoly as it is the only choice for public transportation.&lt;/p&gt;
&lt;h3&gt;Fare Calculation&lt;/h3&gt;
&lt;p&gt;BMTC considers ~2KM distance as a stage and the &lt;a href="https://www.mybmtc.com/general-service?fareid=gns&amp;amp;qt-home_quick_tab_bottom=2" target="_blank"&gt;fares for each stage&lt;/a&gt; are as follows.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/bmtc-fare-charges.png" width="600px"&gt;
&lt;/p&gt;

&lt;p&gt;Let's say, you want to travel from Indira Nagar to BTM Layout, it will cover 5 stages. So, BMTC charges 19₹ for that.&lt;/p&gt;
&lt;h3&gt;Exploitation?&lt;/h3&gt;
&lt;p&gt;If you travel from Indira Nagar KFC signal to Doopanahalli Arch(1.2KM), which comes under 1 stage, you have to pay 5₹.&lt;/p&gt;
&lt;p&gt;On the other hand, if you travel from Indira Nagar KFC signal to Doopanahalli bustop(1.4KM), you have to pay 12₹.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/bmtc-fares.png"&gt;
&lt;/p&gt;

&lt;p&gt;How can BMTC charge 5₹ for the first 1.2KM and 7₹ for the subsequent 0.2KM?  If BMTC charges, 5₹ for 1st stage. Then it should charge 5₹ + extra for next stage. But it shouldn't be more than 10₹.&lt;/p&gt;
&lt;p&gt;You can just take 1 ticket(5₹) for 1st stage(1.2KM) and one more ticket(5₹)  for the next stage(0.2KM).  You can just travel 2 stages with 2 tickets for 10₹.&lt;/p&gt;
&lt;p&gt;Turnsout BMTC is charging 3₹ extra on every ticket which covers atleast 2 stages.  As lakhs of people travel in BMTC buses daily, in a month, this 3₹ turns into crores of rupees.&lt;/p&gt;
&lt;p&gt;I am not sure when BMTC has started charging like this. A month back, I sent them an email asking for an explaination of unfair bus tickets and they haven't replied yet.&lt;/p&gt;
&lt;h3&gt;Update:&lt;/h3&gt;
&lt;p&gt;After sending this to BMTC officials, they have reduced 2nd stage bus fare by 2 Rs. Thanks to &lt;a href="https://twitter.com/philentropist"&gt;Gopala Kallapura&lt;/a&gt;, &lt;a href="https://twitter.com/kracetheking"&gt;Krace Kumar&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/thej"&gt;Thegesh GN&lt;/a&gt; for supporting the issue.&lt;/p&gt;</description><category>bangalore</category><category>governance</category><category>musings</category><guid>https://avilpage.com/2017/02/bmtc-exploiting-crores-from-bangalore-citizens.html</guid><pubDate>Sun, 05 Feb 2017 17:08:16 GMT</pubDate></item><item><title>Refactoring Django With Full Syntax Tree</title><link>https://avilpage.com/2017/01/refactoring-django-with-fst.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Django developers decided to &lt;a href="https://code.djangoproject.com/ticket/23919" target="_blank"&gt;drop Python 2 compatability&lt;/a&gt; in Django 2.0. There are serveral things that should be refactored/removed.&lt;/p&gt;
&lt;p&gt;For example, in Python 2, programmers has to explicitly specify the class &amp;amp; instance when invoking &lt;code&gt;super&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python 3, &lt;code&gt;super&lt;/code&gt; can be invoked without arguments and it will choose right class &amp;amp; instance automatically.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For this refactoring, a simple &lt;code&gt;sed&lt;/code&gt; search/replace should suffice. But, there are several hacks in codebase where super calls the grandparent instead of the parent. So, &lt;code&gt;sed&lt;/code&gt; won't work in such cases. It is hard to refactor them manually and much harder for reviewers as there are 1364 super calls in code base.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;→&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-rI&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"super("&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1364&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So changes has to be scripted. A &lt;a href="https://github.com/ChillarAnand/01/blob/master/python/super_exp.py" target="_blank"&gt;simple python script&lt;/a&gt; to replace super calls by class names will fail to capture classes with on top of them, classes with decorators and nested classes.&lt;/p&gt;
&lt;p&gt;To handle all these cases, this python script gets more complicated and there is no guarantee that it can handle all edge cases. So, a better choice is to use syntax trees.&lt;/p&gt;
&lt;p&gt;Python has &lt;a href="https://docs.python.org/3/library/ast.html" target="_blank"&gt;ast module&lt;/a&gt; to convert code to AST but it can't convert AST back to code. There are 3rd party packages like &lt;a href="https://pypi.python.org/pypi/astor" target="_blank"&gt;astor&lt;/a&gt; which can do this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# this is a comment&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"hello world"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Converting above code to AST and then converting back gives this&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hello world'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Code to AST is a lossy transformation as they cannot preserve empty lines, comments and code formatting.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;ast_to_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_to_ast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_code&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;source_code&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For lossless transformation, FST(Full Syntax Trees) is needed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;fst_to_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_to_fst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_code&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;source_code&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/PyCQA/redbaron" target="_blank"&gt;RedBaron&lt;/a&gt; package provides FST for given piece of code. With this, just locate super calls, find nearest class node, check class name with super and replace accordingly. With RedBaron, this refactoring can be done in &lt;a href="https://github.com/ChillarAnand/01/blob/master/python/redbaron_super.py" target="_blank"&gt;less than 10 lines&lt;/a&gt; of code.&lt;/p&gt;
&lt;p&gt;RedBaron has good documentation with relveant examples and its API is similar to BeautifulSoup. To write code that modifies code RedBaron seems to be an apt choice.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="https://github.com/timgraham" target="_blank"&gt;Tim Graham&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/aaugustin" target="_blank"&gt;Aymeric Augustin&lt;/a&gt; for &lt;a href="https://github.com/django/django/pull/7905/commits/d6eaf7c0183cd04b78f2a55e1d60bb7e59598310" target="_blank"&gt;reviewing the patch&lt;/a&gt;.&lt;/p&gt;</description><category>django</category><category>featured</category><category>python</category><guid>https://avilpage.com/2017/01/refactoring-django-with-fst.html</guid><pubDate>Sun, 29 Jan 2017 17:51:37 GMT</pubDate></item><item><title>Why Blog Posts Are Better Than Scientific Papers?</title><link>https://avilpage.com/2017/01/blog_posts_are_better_than_scientific_papers/</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Titus Brown wrote a blog post on why &lt;a href="http://ivory.idyll.org/blog/2017-top-ten-reasons-blog-posts.html"&gt;blog posts are better than scientific papers&lt;/a&gt;. Here are few more reasons for that.&lt;/p&gt;
&lt;h3&gt;Fast&lt;/h3&gt;
&lt;p&gt;Publishing blog posts is lightning fast(how fast can you type?). You can just publish it with a click after writing. However with scientific papers you have to wait months to get your work published.&lt;/p&gt;
&lt;h3&gt;Mutability&lt;/h3&gt;
&lt;p&gt;Blog posts are easy to edit. If you are using a version controlled system like git, any one can easily collaborate. You can also leave comments on (most) blog posts and can have discussion with the author and/or others. Scientific papers once published are hard to change.&lt;/p&gt;
&lt;h3&gt;No Gatekeepers&lt;/h3&gt;
&lt;p&gt;To publish blog posts, you can setup your own blog or use services like &lt;a href="http://medium.com"&gt;medium&lt;/a&gt;. There are no gatekeepers who says that you can't publish a blog post because they thinks its not worth it.&lt;/p&gt;
&lt;h3&gt;Organic&lt;/h3&gt;
&lt;p&gt;Blog posts tend to be casual and organic. You can crack a joke and readers will enjoy it. Scientific papers are formal. You spray some sarcasm and your paper never gets published.&lt;/p&gt;</description><category>musings</category><guid>https://avilpage.com/2017/01/blog_posts_are_better_than_scientific_papers/</guid><pubDate>Sun, 08 Jan 2017 17:03:38 GMT</pubDate></item><item><title>What Is The Meaning Of Life?</title><link>https://avilpage.com/2016/12/the-meaning-of-life.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;The meaning of life is&lt;/p&gt;
&lt;blockquote cite="https://en.oxforddictionaries.com/definition/life"&gt;

the condition that distinguishes animals and plants from inorganic matter, including the capacity for growth, reproduction, functional activity, and continual change preceding death.

&lt;/blockquote&gt;

&lt;p&gt;Source: Oxford Dictionary&lt;/p&gt;</description><category>featured</category><category>musings</category><guid>https://avilpage.com/2016/12/the-meaning-of-life.html</guid><pubDate>Sun, 25 Dec 2016 18:29:23 GMT</pubDate></item><item><title>Detect &amp; Correct Skew In Images Using Python</title><link>https://avilpage.com/2016/11/detect-correct-skew-images-python.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When scanning a document, a slight skew gets into the scanned image. If you are using the scanned image to extract information from it, detecting and correcting skew is crucial.&lt;/p&gt;
&lt;p&gt;There are several techniques that are used to skew correction.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Projection profile method&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hough transform&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Topline method&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scanline method&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, projection profile method is the simplest and easiest way to determine skew in documents in the range ±5°. Lets take a part of scanned image and see how to correct skew.&lt;/p&gt;
&lt;p&gt;In this method, we will convert image to black (absence of pixel) &amp;amp; white (presence of pixel). Now image is projected vertically to get a histogram of pixels. Now image is rotated at various angles and above process is repeated. Wherver we find maximum diffrence between peaks, that will be the best angle.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;matplotlib.pyplot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;numpy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;PIL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;scipy.ndimage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;interpolation&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;inter&lt;/span&gt;

&lt;span class="n"&gt;input_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# convert to binary&lt;/span&gt;
&lt;span class="n"&gt;wd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ht&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;span class="n"&gt;pix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getdata&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bin_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ht&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wd&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bin_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gray'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;savefig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'binary.png'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;find_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;


&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;angles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;angle&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;angles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bin_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;best_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;best_angle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;angles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;best_score&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Best angle: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;formate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;best_angle&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# correct skew&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bin_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;best_angle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromarray&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"uint8"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"RGB"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'skew_corrected.png'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;
&lt;p align="center"&gt;&lt;img align="center" src="https://avilpage.com/skew_python/original.png"&gt;&lt;/p&gt;
&lt;p align="center"&gt;Original Image&lt;/p&gt;
&lt;hr&gt;

&lt;p align="center"&gt;&lt;img align="center" src="https://avilpage.com/skew_python/gray.png"&gt;&lt;/p&gt;
&lt;p align="center"&gt;Black &amp;amp; white image&lt;/p&gt;
&lt;hr&gt;

&lt;p align="center"&gt;&lt;img align="center" src="https://avilpage.com/skew_python/hist_0.png"&gt;&lt;/p&gt;
&lt;p align="center"&gt;Histogram of image&lt;/p&gt;
&lt;hr&gt;

&lt;p align="center"&gt;&lt;img align="center" src="https://avilpage.com/skew_python/hist_scores.png"&gt;&lt;/p&gt;
&lt;p align="center"&gt;Scores at various angles&lt;/p&gt;
&lt;hr&gt;

&lt;p align="center"&gt;&lt;img align="center" src="https://avilpage.com/skew_python/hist_best.png"&gt;&lt;/p&gt;
&lt;p align="center"&gt;Histogram at 2° (best angle)&lt;/p&gt;
&lt;hr&gt;

&lt;p align="center"&gt;&lt;img align="center" src="https://avilpage.com/skew_python/skew_corrected.png"&gt;&lt;/p&gt;
&lt;p align="center"&gt;Skew corrected image&lt;/p&gt;

&lt;p&gt;Here we have done only one iteration to find best angle. To get better accuracy, we can search over at (2 ± 0.5)°. This process can be repeated until we find a suitable level of accuracy.&lt;/p&gt;</description><category>featured</category><category>python</category><guid>https://avilpage.com/2016/11/detect-correct-skew-images-python.html</guid><pubDate>Sat, 12 Nov 2016 12:11:17 GMT</pubDate></item><item><title>Why I Use CyanogenMod?</title><link>https://avilpage.com/2016/10/why-use-cyanogenmod.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When listening to music, to switch tracks I want to use volume buttons. For this I have to use &lt;a href="https://play.google.com/store/apps/details?id=com.silentlexx.volbtntrackctrl&amp;amp;hl=en"&gt;Pocket Skip Track&lt;/a&gt; app.
CyanogenMod has inbuilt support for that.&lt;/p&gt;
&lt;p&gt;To interact with mobile from computer over wifi, &lt;a href="https://play.google.com/store/apps/details?id=com.ttxapps.wifiadb"&gt;wifi adb&lt;/a&gt; is required. CyanogenMod provides an option to enable this in &lt;code&gt;Developer Options&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To put mobile in recovery mode, &lt;a href="http://repo.xposed.info/module/com.ceco.kitkat.gravitybox"&gt;Gravity Box&lt;/a&gt; is required. This should be used only after installing Xposed framework. CyanogenMod has &lt;code&gt;Advanced reboot&lt;/code&gt; which provides option to put phone in recovery mode.&lt;/p&gt;
&lt;p&gt;Battery icon in status bar is very small. Having a text percentage indicator will be more useful. For this &lt;a href="https://play.google.com/store/apps/details?id=de.kroegerama.android4batpercent"&gt;battery percentage&lt;/a&gt; is required.
CyanogenMod has inbuilt circle/text indicators.&lt;/p&gt;
&lt;p&gt;Auto brighness stopped working after I have rooted Moto G4 plus. I had to use &lt;a href="https://play.google.com/store/apps/details?id=com.urbandroid.lux"&gt;twilight&lt;/a&gt; for auto brighness adjustment. With CyanogenMod, it is working fine. It also has a night mode option.&lt;/p&gt;
&lt;p&gt;With stock android, auto rotate won't work in all directions. &lt;a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.setorientation"&gt;Set orientation&lt;/a&gt; app is required for that. CyanogenMod has inbuilt support for that.&lt;/p&gt;
&lt;p&gt;To adapt mobile display to the time of the day, flux app is required on stock android. CyanogenMod has inbuilt option for this.&lt;/p&gt;
&lt;p&gt;To get superuser permissions, I have to root stock android. CyanogenMod comes with root permissions. To run &lt;code&gt;adb&lt;/code&gt; as root on stock android, &lt;code&gt;adbd insecure&lt;/code&gt; app is required. CyanogenMod works without it.&lt;/p&gt;
&lt;p&gt;Stock android also doesn't provide any options to customize status bar. CyanogenMod has several options to customize it.&lt;/p&gt;
&lt;p&gt;There are several other things where CyanogenMod excels when compared to stock android like themes, privacy guard e.t.c. However, CyanogenMod comes with a lot of inbuilt features(batteries included) and that is the main reason for me to use it.&lt;/p&gt;</description><category>android</category><guid>https://avilpage.com/2016/10/why-use-cyanogenmod.html</guid><pubDate>Mon, 31 Oct 2016 14:05:09 GMT</pubDate></item><item><title>Remove Clock From LockScreen/StatusBar On Android</title><link>https://avilpage.com/2016/09/remove-clock-lock-screen-status-bar-android.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I have been living without time from a few years and it is a bliss. I have removed time from my laptop. For android mobile, I couldn't find a reliable way to remove time and I used to change timezone to a random zone. With Xposed framework we can remove clock from lock screen and status bar.&lt;/p&gt;
&lt;p&gt;Before proceeding, make sure your phone is &lt;a href="http://www.xda-developers.com/root/"&gt;rooted&lt;/a&gt; and &lt;a href="http://repo.xposed.info/module/de.robv.android.xposed.installer"&gt;Xposed framework&lt;/a&gt; is installed.&lt;/p&gt;
&lt;h4&gt;Remove Clock From LockScreen&lt;/h4&gt;
&lt;p&gt;To remove clock from lockscreen, download &lt;a href="http://repo.xposed.info/module/com.ssrdroide.lockscreenwidgets"&gt;Lock screen widgets&lt;/a&gt; module and activate it.&lt;/p&gt;
&lt;p&gt;If you open it, it has an option to hide date and time.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_0.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;h4&gt;Remove Time From StatusBar&lt;/h4&gt;
&lt;p&gt;To remove clock from status bar, you have to install &lt;a href="http://repo.xposed.info/module/com.ceco.marshmallow.gravitybox"&gt;GravityBox&lt;/a&gt;. Open GravityBox and goto statusbar settings&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_3.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_4.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_5.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p&gt;If you are already using CyanogenMod, there is an option to hide time in settings.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_1.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_2.png" height="400px" width="220"&gt;
&lt;/p&gt;

&lt;p&gt;Once you do this, you will have a neat lockscreen without any time on it.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/remove_clock_android/remove_clock_anrdoid_6.png" height="400px" width="220"&gt;
&lt;/p&gt;</description><category>android</category><category>how-to</category><guid>https://avilpage.com/2016/09/remove-clock-lock-screen-status-bar-android.html</guid><pubDate>Thu, 15 Sep 2016 13:24:38 GMT</pubDate></item><item><title>Detecting USB Events In Ubuntu With Python</title><link>https://avilpage.com/2016/09/detecting-device-events-in-ubuntu-with-python.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Udev"&gt;udev&lt;/a&gt; is responsible for managing devices on Linux. It provides &lt;code&gt;udevadm&lt;/code&gt;, a CLI utility to monitor and control devices.&lt;/p&gt;
&lt;p&gt;If we run &lt;code&gt;udevadm monitor&lt;/code&gt; on terminal and connect a USB drive or hard disk or a mobile via USB to your computer, it will show that kernel has detected the device and it will send a signal to udev about it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;→&lt;span class="w"&gt; &lt;/span&gt;udevadm&lt;span class="w"&gt; &lt;/span&gt;monitor
monitor&lt;span class="w"&gt; &lt;/span&gt;will&lt;span class="w"&gt; &lt;/span&gt;print&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;received&lt;span class="w"&gt; &lt;/span&gt;events&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;:
UDEV&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;event&lt;span class="w"&gt; &lt;/span&gt;which&lt;span class="w"&gt; &lt;/span&gt;udev&lt;span class="w"&gt; &lt;/span&gt;sends&lt;span class="w"&gt; &lt;/span&gt;out&lt;span class="w"&gt; &lt;/span&gt;after&lt;span class="w"&gt; &lt;/span&gt;rule&lt;span class="w"&gt; &lt;/span&gt;processing
KERNEL&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;kernel&lt;span class="w"&gt; &lt;/span&gt;uevent

KERNEL&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4336&lt;/span&gt;.899091&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt;      &lt;/span&gt;/devices/pci0000:00/0000:00:14.0/usb1/1-2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;usb&lt;span class="o"&gt;)&lt;/span&gt;
KERNEL&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4336&lt;/span&gt;.899774&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt;      &lt;/span&gt;/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;usb&lt;span class="o"&gt;)&lt;/span&gt;
KERNEL&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4336&lt;/span&gt;.902553&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt;      &lt;/span&gt;/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;usb&lt;span class="o"&gt;)&lt;/span&gt;
UDEV&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4336&lt;/span&gt;.911201&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt;      &lt;/span&gt;/devices/pci0000:00/0000:00:14.0/usb1/1-2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;usb&lt;span class="o"&gt;)&lt;/span&gt;
UDEV&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4336&lt;/span&gt;.936453&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt;      &lt;/span&gt;/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;usb&lt;span class="o"&gt;)&lt;/span&gt;
UDEV&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4337&lt;/span&gt;.947174&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt;      &lt;/span&gt;/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;usb&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://pypi.python.org/pypi/pyudev"&gt;Pyudev&lt;/a&gt;, a third party package provides python bindings for udev. It can be installed with &lt;code&gt;pip install pyudev&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With this we can create a simple monitor to detect USB events.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pyudev&lt;/span&gt;

&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyudev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;monitor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyudev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Monitor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_netlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;monitor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subsystem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'usb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monitor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'add'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt; connected'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="c1"&gt;# do something&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save this to a file say monitor.py and run it with &lt;code&gt;python monitor.py&lt;/code&gt; and connect a mobile or pendrive and it will show something like this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;Device&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;connected
Device&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/sys/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;connected
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here we are just detecting &lt;code&gt;add&lt;/code&gt; event. Similary we can detect other events like &lt;code&gt;delete&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is useful for automatically running shell scripts once the device gets plugged or unplugged.&lt;/p&gt;</description><category>linux</category><category>python</category><category>usb</category><guid>https://avilpage.com/2016/09/detecting-device-events-in-ubuntu-with-python.html</guid><pubDate>Fri, 02 Sep 2016 13:24:38 GMT</pubDate></item><item><title>Migrate From Blogger To Static Site (Nikola)</title><link>https://avilpage.com/2016/08/migrate-from-blogger-to-static-site-nikola.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Long back I have started this blog on &lt;a href="https://blogger.com"&gt;blogger&lt;/a&gt; platform. Now I choose to migrate to a static because of limitations of blogger.&lt;/p&gt;
&lt;p&gt;Blogger has a simple editor in browser to write posts in html. With static site, you can write post in your editor in markdown and keep them in version control system like git.&lt;/p&gt;
&lt;p&gt;Jekyll, Pelican, Lektor were my initial choices for static site generators. Unfortunately, they didn't had any useful plugins for smooth migration of data from blogger. Then I stumbled across &lt;a href="https://plugins.getnikola.com/#import_blogger"&gt;import_blogger&lt;/a&gt; plugin of &lt;a href="https://getnikola.com"&gt;Nikola&lt;/a&gt; and it is able to migrate text content, images without any issues. So, I decided to use Nikola.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://getnikola.com"&gt;Nikola&lt;/a&gt; has great documentation and setup was simpler. I used &lt;code&gt;import_blogger&lt;/code&gt; plugin and imported all the data. All the posts and pages were working well with exact same urls.&lt;/p&gt;
&lt;p&gt;Blogger tags all posts of particular label under &lt;code&gt;/search/label/foo&lt;/code&gt;. I have used these urls in some posts. Nikola shows posts under &lt;code&gt;/categories/foo.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is where nikola &lt;code&gt;REDIRECTIONS&lt;/code&gt; come in handy. Using this, a list of from &amp;amp; to urls can be mapped. I wrote a simple function for redirections and then enabled &lt;code&gt;STRIP_INDEXES&lt;/code&gt; which removes trailing &lt;code&gt;.html&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'python'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'emacs'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'zen'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'django'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'chrome'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;LABEL_REDIRECTIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;LABEL_REDIRECTIONS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
        &lt;span class="s1"&gt;'/search/label/&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;/index.html'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s1"&gt;'/categories/&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since I stripped &lt;code&gt;.html&lt;/code&gt; from urls, old urls broke. So I generated a list of old urls and wrote another function to redirect them to new urls.&lt;/p&gt;
&lt;p&gt;Nikola has few builtin themes. I wanted something minimalistic and so I rolled out custom theme which you are seeing right now.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="https://github.com/punchagan"&gt;Puneeth Chaganti&lt;/a&gt;, &lt;a href="https://github.com/Kwpolska"&gt;Chris Warrick&lt;/a&gt;, &lt;a href="https://github.com/ralsina"&gt;Roberto Alsina&lt;/a&gt; for helping me with migration.&lt;/p&gt;</description><category>blogging</category><guid>https://avilpage.com/2016/08/migrate-from-blogger-to-static-site-nikola.html</guid><pubDate>Sun, 07 Aug 2016 11:32:15 GMT</pubDate></item><item><title>emblem-mode for Emacs</title><link>https://avilpage.com/2016/07/emblem-mode-for-emacs.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Emblem.js is a ember friendly templating engine used as an alternative for handlebars.js.&lt;/p&gt;
&lt;p&gt;Emblem.js doesn't have any official plugins for emacs. However they recommend to use slim plugins as they are similar.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;slim-mode&lt;/code&gt; is available on melpa. To install it, run&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;M&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;slim&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After installing it, activate &lt;code&gt;slim-mode&lt;/code&gt; by running &lt;code&gt;M-x slim-mode&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead of activating manually, &lt;code&gt;auto-mode-alist&lt;/code&gt; can be used to set major modes that needs to activated for files with specific extension. To activate slim-mode for emblem files which will be ending with &lt;code&gt;.em&lt;/code&gt; or &lt;code&gt;.emblem&lt;/code&gt;, use&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-to-list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'auto-mode-alist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\\.\\(em\\|emblem\\)"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;slim-mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By adding this line to emacs configuration file, slim-mode gets activated for emblem.js files.&lt;/p&gt;</description><category>emacs</category><guid>https://avilpage.com/2016/07/emblem-mode-for-emacs.html</guid><pubDate>Mon, 25 Jul 2016 17:32:35 GMT</pubDate></item><item><title>Auto Completion For Custom Search Engines In Chrome</title><link>https://avilpage.com/2016/06/auto-completion-for-custom-search.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
      &lt;span style="font-size: 16px; font-weight: normal; line-height: 25.6px;"&gt;If we have to search for a video on YouTube or a product on Amazon, we will open
      up that site first and then we will search for it.&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;a href="https://cloud.githubusercontent.com/assets/4463796/15986478/89999bda-3026-11e6-9460-9b0c2d4db4d9.png" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;" target="_blank"&gt;&lt;img alt="Chrome-custom-search-autocompletion1" src="https://cloud.githubusercontent.com/assets/4463796/15986478/89999bda-3026-11e6-9460-9b0c2d4db4d9.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    To avoid this, Chrome allows us to search using custom search engines without visiting the site first. In chrome search settings, we can assign a single
    letter to a custom search engine.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;a href="https://cloud.githubusercontent.com/assets/4463796/15986479/899a642a-3026-11e6-8084-beddf28bf8d6.png" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;" target="_blank"&gt;&lt;img alt="Chrome-custom-search-autocompletion1" src="https://cloud.githubusercontent.com/assets/4463796/15986479/899a642a-3026-11e6-8084-beddf28bf8d6.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    Now if we go to browser, type &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;y&lt;/code&gt; and
    hit &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Tab&lt;/code&gt;,
    it prompts for YouTube search instead of default search.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;a href="https://cloud.githubusercontent.com/assets/4463796/15986476/89951240-3026-11e6-99ad-cc8cf9127605.png" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;" target="_blank"&gt;&lt;img alt="Chrome-custom-search-autocompletion1" src="https://cloud.githubusercontent.com/assets/4463796/15986476/89951240-3026-11e6-99ad-cc8cf9127605.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    This is handy. But the major problem with this approach is there won't be autocompletion in chrome address bar.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    This is where vimium comes into picture. Vimium provides auto completion for custom search engines.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    You can install it &lt;a href="https://chrome.google.com/webstore/detail/dbepggeogbaibhgnhhndojpepiihcmeb" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;from chrome webstore&lt;/a&gt;. Once it is installed, go to Vimium options and
    add youtube search to custom search engines.
    &lt;/div&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;

&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;y: http://www.youtube.com/results?search_query=%s Youtube&lt;br&gt;&lt;/code&gt;
&lt;/pre&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    Also add a custom key map for this search.
    &lt;/div&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;

&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;map y Vomnibar.activateInNewTab keyword=y&lt;br&gt;&lt;/code&gt;
&lt;/pre&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    If we just press &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;y&lt;/code&gt;,
    it open youtube custom search with autocompletion.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;a href="https://cloud.githubusercontent.com/assets/4463796/15986477/8996f3e4-3026-11e6-8c83-8a74f0ab84fb.png" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;" target="_blank"&gt;&lt;img alt="Chrome-custom-search-autocompletion1" src="https://cloud.githubusercontent.com/assets/4463796/15986477/8996f3e4-3026-11e6-8c83-8a74f0ab84fb.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
        Now in every page, we have autocompletion for custom search engines.&lt;br&gt;

    &lt;/div&gt;
  &lt;/div&gt;</description><category>browser</category><guid>https://avilpage.com/2016/06/auto-completion-for-custom-search.html</guid><pubDate>Sat, 11 Jun 2016 12:07:00 GMT</pubDate></item><item><title>Concurrent Downloads - Bash Vs Python</title><link>https://avilpage.com/2016/05/concurrent-downloads-bash-vs-python.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                I just found one more free telugu book &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Graded
      readings in modern literary Telugu&lt;/code&gt; by Golla Narayanaswami Reddy and Dan M Matson in &lt;a href="http://dsal.uchicago.edu/digbooks/dig_toc.html?BOOKID=PL4775.R4_1967" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;Digital South Asia Library&lt;/a&gt;.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                Unfortunately they didn't provide it as an ebook but as a set of 221 tif images.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                I wrote a simple for loop in shell which downloaded all images one by one using &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;wget&lt;/code&gt;.
            &lt;/div&gt;
            &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;
      $ base_url=&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;http://dsal.uchicago.edu&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br&gt;$ url=&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;&lt;span class="pl-smi" style="box-sizing: border-box; color: #333333;"&gt;$base_url&lt;/span&gt;/digbooks/images/PL4775.R4_1967/PL4775.R4_1967_%03g.gif&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br&gt;$ &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;time&lt;/span&gt; -p sh -c &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;for i in $(seq -f $url 1 221); do; wget $i; done;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                I took 375 seconds for that. This was too slow. So I tried to download them parallelly using xargs.
            &lt;/div&gt;
            &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;
      $ &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;time&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;echo&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;$(&lt;/span&gt;seq -f &lt;span class="pl-smi" style="box-sizing: border-box; color: #333333;"&gt;$url&lt;/span&gt; 1 221&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;|&lt;/span&gt; xargs -n 1 -P 36 wget&lt;/pre&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                My laptop has a quad core processor. So I tried with 20, 24, 28, 32 process at a time.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                With &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;wget+xargs&lt;/code&gt;,
                the best timing is 13 seconds (CPU: 15%, Process: 28).
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                Again I tried downloading them parallelly but with GNU parallel.
            &lt;/div&gt;
            &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;
      $ &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;time&lt;/span&gt; seq -f &lt;span class="pl-smi" style="box-sizing: border-box;"&gt;$url&lt;/span&gt; 1 221 &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;|&lt;/span&gt; parallel -j36 wget {}&lt;/pre&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                With &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;wget+parallel&lt;/code&gt;,
                the best timing is 12 seconds (CPU: 48%, Process: 24).
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                Here is cpu consumption and time taken at each step.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;a href="https://cloud.githubusercontent.com/assets/4463796/15634659/08965d50-25e7-11e6-9f3e-02fe008997a1.png" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;" target="_blank"&gt;&lt;img alt="paralle_python_bash2" src="https://cloud.githubusercontent.com/assets/4463796/15634659/08965d50-25e7-11e6-9f3e-02fe008997a1.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                Once I have done with bash, I decided to try the same things with Python and see how it goes.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                I wrote a simple script using requests to download images.
            &lt;/div&gt;
            &lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;
                    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; shutil&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; sys&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; concurrent &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; futures&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; requests&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;download_image&lt;/span&gt;(&lt;span class="pl-smi" style="box-sizing: border-box;"&gt;url&lt;/span&gt;):&lt;br&gt;    r &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; requests.get(url)&lt;br&gt;    file_name &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; url.split(&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;/&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)[&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;]&lt;br&gt;    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;with&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;open&lt;/span&gt;(file_name, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;wb&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;as&lt;/span&gt; fh:&lt;br&gt;        fh.write(r.content)&lt;br&gt;&lt;br&gt;&lt;br&gt;base_url &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;http://dsal.uchicago.edu&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br&gt;book_url &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; base_url &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;+&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;/digbooks/images/PL4775.R4_1967/PL4775.R4_1967_&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;{}&lt;/span&gt;.gif&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br&gt;urls &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; [book_url.format(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;str&lt;/span&gt;(i).zfill(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;)) &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;for&lt;/span&gt; i &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;range&lt;/span&gt;(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;221&lt;/span&gt;)]&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;download_serially&lt;/span&gt;():&lt;br&gt;    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;for&lt;/span&gt; url &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; urls:&lt;br&gt;        download_image(url)&lt;br&gt;&lt;br&gt;download_serially()&lt;/pre&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                This took 244 seconds.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                To download images parallelly, I have used &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Threadpoolexecutor&lt;/code&gt; from &lt;a href="https://docs.python.org/3.5/library/concurrent.futures.html" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;concurrent module&lt;/a&gt;.
            &lt;/div&gt;
            &lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;
                    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;download_parallely&lt;/span&gt;():&lt;br&gt;    workers &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;int&lt;/span&gt;(sys.argv[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;])&lt;br&gt;&lt;br&gt;    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;with&lt;/span&gt; futures.ThreadPoolExecutor(&lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;max_workers&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt;workers) &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;as&lt;/span&gt; executor:&lt;br&gt;        result &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; executor.map(download_image, urls)&lt;br&gt;&lt;br&gt;download_parallely()&lt;/pre&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                I used previous script but just added one more function which queues tasks. Then I have executed the script with several options.
            &lt;/div&gt;
            &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;
      $ &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;time&lt;/span&gt; python down.py 28&lt;/pre&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                Threadpoolexecutor documentation uses 5 times number of processors as max_workers by default. I tried same options which I have used for bash. Here is
                the overall comparision.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                With &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;requests+ThreadPoolExecutor&lt;/code&gt;,
                the best timing is 12 seconds (CPU: 36%, Process: 28).
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                Here is the overall comparision.
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;a href="https://cloud.githubusercontent.com/assets/4463796/15634653/edadbb50-25e6-11e6-8f59-c908ca7d65b2.png" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;" target="_blank"&gt;&lt;img alt="paralle_python_bash" src="https://cloud.githubusercontent.com/assets/4463796/15634653/edadbb50-25e6-11e6-8f59-c908ca7d65b2.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;
            &lt;/div&gt;
            &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
                &lt;span style="line-height: 25.6px;"&gt;For a simple concurrent download, xargs+wget seems to be the best option.&lt;/span&gt;
            &lt;/div&gt;
        &lt;/div&gt;</description><category>command-line</category><category>python</category><guid>https://avilpage.com/2016/05/concurrent-downloads-bash-vs-python.html</guid><pubDate>Sun, 29 May 2016 11:55:00 GMT</pubDate></item><item><title>Emacs - Browsing Projects With Etags</title><link>https://avilpage.com/2016/04/emacs-browsing-projects-with-etags.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;A tag is a reference to a sub unit in a program. A tag references syntactic elements like functions, classes e.t.c. A tags table consists of list of tag names and their positions in corresponding files.&lt;/div&gt;&lt;h4 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.25em; line-height: 1.4; margin-bottom: 16px; margin-top: 1em; position: relative;"&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#creating-tags-table" id="user-content-creating-tags-table" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1.2; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;Creating Tags Table&lt;/h4&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;A tags table can be generated by &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Create-Tags-Table.html" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;etags&lt;/a&gt; program. If you are using Ubuntu machine, you can install it with&lt;/div&gt;&lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;sudo apt-get install exuberant-ctags&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Now, you can generate tags for a file with&lt;/div&gt;&lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;etags input_file&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Depending on the project, we can also generate tags for a particular type. For example, we can generate tags for all python files using&lt;/div&gt;&lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;find &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;.&lt;/span&gt; -name &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;*.py&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt; -exec etags -a {} &lt;span class="pl-cce" style="box-sizing: border-box;"&gt;\;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.25em; line-height: 1.4; margin-bottom: 16px; margin-top: 1em; position: relative;"&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#browsing-tags" id="user-content-browsing-tags" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1.2; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;Browsing Tags&lt;/h4&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;This tag tables enables you to jump to definition of any tag. You can place cursor on a tag and press&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;M-.&lt;/code&gt;(find-tag) which takes you to definition of that tag. If you want to go back to previous location, you can use &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;M-*&lt;/code&gt;(pop-tag -mark). There are &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Find-Tag.html#Find-Tag" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;several functions&lt;/a&gt; which help to navigate tags.&lt;/div&gt;&lt;h4 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.25em; line-height: 1.4; margin-bottom: 16px; margin-top: 1em; position: relative;"&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#tips" id="user-content-tips" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1.2; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;Tips&lt;/h4&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;a href="https://github.com/jixiuf/helm-etags-plus" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;ctags-update&lt;/a&gt; is a third party package which automatically updates TAGS file when new files are created.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;In addition to them, helm provides a function called &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;helm-semantic&lt;/code&gt; which shows all available tags in the current file. This works without TAGS file. Helm also has &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;helm-etags-select&lt;/code&gt; which provides helm interface to select tags.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;If you are working with a python projects, you can use &lt;a href="https://github.com/jorgenschaefer/elpy" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;elpy&lt;/a&gt; which navigates tags (using Jedi in the backend) without any TAGS file.&lt;/div&gt;&lt;h1 style="border-bottom-color: rgb(238, 238, 238); border-bottom-style: solid; border-bottom-width: 1px; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 2.25em; line-height: 1.2; margin: 1em 0px 16px; padding-bottom: 0.3em; position: relative;"&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#adding-attributes-to-django-forms" id="user-content-adding-attributes-to-django-forms" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;&lt;/h1&gt;&lt;/div&gt;</description><category>emacs</category><category>python</category><category>tech</category><guid>https://avilpage.com/2016/04/emacs-browsing-projects-with-etags.html</guid><pubDate>Sun, 17 Apr 2016 10:41:00 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #6 - Make Deleting Easy In Admin</title><link>https://avilpage.com/2016/03/django-tips-make-deleting-easy-in-admin.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Lets say we have a model as shown in some project.&lt;/div&gt;&lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; django.db &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; models&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;class&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;Resource&lt;/span&gt;(&lt;span class="pl-e" style="box-sizing: border-box; color: #795da3;"&gt;models&lt;/span&gt;.&lt;span class="pl-e" style="box-sizing: border-box; color: #795da3;"&gt;Model&lt;/span&gt;):&lt;br&gt;    &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;"""&lt;/span&gt;&lt;br&gt;&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;    Model to hold resources for books.&lt;/span&gt;&lt;br&gt;&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;    &lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"""&lt;/span&gt;&lt;/span&gt;&lt;br&gt;    book &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; models.ForeignKey(&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;Book&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;    book_type &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; models.IntegerField()&lt;br&gt;    url &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; models.URLField()&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;This model can be registered in admin as follows.&lt;/div&gt;&lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; django.contrib &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; admin&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; . &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; models&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;class&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;ResourceAdmin&lt;/span&gt;(&lt;span class="pl-e" style="box-sizing: border-box; color: #795da3;"&gt;admin&lt;/span&gt;.&lt;span class="pl-e" style="box-sizing: border-box; color: #795da3;"&gt;ModelAdmin&lt;/span&gt;):&lt;br&gt;    list_display &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; (&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;book&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;book_type&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;url&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;br&gt;admin.site.register(models.Resource, ResourceAdmin)&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;This will generate a nice admin interface to modify the data.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;a href="https://cloud.githubusercontent.com/assets/4463796/13577519/d6e3bb1e-e4b8-11e5-935b-41633883fed3.png" style="box-sizing: border-box; color: #4078c0; text-decoration: none;" target="_blank"&gt;&lt;img alt="django-admin-delete" src="https://cloud.githubusercontent.com/assets/4463796/13577519/d6e3bb1e-e4b8-11e5-935b-41633883fed3.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Now if we want to delete a record, we need to follow these steps.&lt;/div&gt;&lt;ul style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px; margin-top: 0px; padding: 0px 0px 0px 2em;"&gt;&lt;li style="box-sizing: border-box;"&gt;First, we have to select that record&lt;/li&gt;&lt;li style="box-sizing: border-box;"&gt;Next, we have to click on the action dropdown&lt;/li&gt;&lt;li style="box-sizing: border-box;"&gt;Next, we have to select &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;delete&lt;/code&gt; action&lt;/li&gt;&lt;li style="box-sizing: border-box;"&gt;Next, we have to click &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Go&lt;/code&gt; button.&lt;/li&gt;&lt;li style="box-sizing: border-box;"&gt;In the next page we have to confirm that we have to delete.&lt;/li&gt;&lt;/ul&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Just to delete a single record, we have to click 5 times. That's too many clicks for a single action.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;To simplify the process, we can have simple &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;delete&lt;/code&gt; button for the objects as shown. This can be achieved by writing a function which will insert delete button for every record.&lt;/div&gt;&lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; django.contrib &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; admin&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; . &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; models&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;class&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;ResourceAdmin&lt;/span&gt;(&lt;span class="pl-e" style="box-sizing: border-box; color: #795da3;"&gt;admin&lt;/span&gt;.&lt;span class="pl-e" style="box-sizing: border-box; color: #795da3;"&gt;ModelAdmin&lt;/span&gt;):&lt;br&gt;    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;delete&lt;/span&gt;(&lt;span class="pl-smi" style="box-sizing: border-box;"&gt;self&lt;/span&gt;, &lt;span class="pl-smi" style="box-sizing: border-box;"&gt;obj&lt;/span&gt;):&lt;br&gt;        &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;return&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&amp;lt;input type="button" value="Delete" onclick="location.href=&lt;span class="pl-cce" style="box-sizing: border-box;"&gt;\'&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;%s&lt;/span&gt;/delete/&lt;span class="pl-cce" style="box-sizing: border-box;"&gt;\'&lt;/span&gt;" /&amp;gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;.format(obj.pk)&lt;br&gt;&lt;br&gt;    delete.allow_tags &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;True&lt;/span&gt;&lt;br&gt;    delete.short_description &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;Delete object&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;    list_display &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; (&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;book&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;,  &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;book_type&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;url&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;delete&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;br&gt;admin.site.register(models.Book)&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Now we have an admin with delete button for the records.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;a href="https://cloud.githubusercontent.com/assets/4463796/13577518/d6de98fa-e4b8-11e5-9303-7f88ec929464.png" style="box-sizing: border-box; color: #4078c0; outline: 0px;" target="_blank"&gt;&lt;img alt="django-admin-delete" src="https://cloud.githubusercontent.com/assets/4463796/13577518/d6de98fa-e4b8-11e5-9303-7f88ec929464.png" style="border: 0px; box-sizing: border-box; max-width: 100%;"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;To delete an object, just click on &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;delete&lt;/code&gt; button and then confirm to delete it. Now, we are deleting objects with just 2 clicks.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;br&gt;Read more &lt;a href="http://www.avilpage.com/search/label/django%20tips" target=""&gt;django tips&lt;/a&gt;.&lt;br&gt;Read more &lt;a href="http://www.avilpage.com/search/label/django"&gt;posts about django&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2016/03/django-tips-make-deleting-easy-in-admin.html</guid><pubDate>Mon, 07 Mar 2016 12:08:00 GMT</pubDate></item><item><title>Auto Convert &amp; Upload Books To Kindle</title><link>https://avilpage.com/2016/02/auto-convert-upload-books-to-kindle.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I have ebooks in various formats like pdf, epub, mobi e.t.c. If I want to read books in laptop, I could use ebook reader like &lt;a href="https://github.com/kovidgoyal/calibre" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;Calibre&lt;/a&gt; which can open supports most of the formats.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;If I have to read them on Kindle paperwhite, it becomes a problem as it supports only few formats. So whenever I get an ebook, I have to convert it to mobi format and send it to kindle.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I can connect kindle to laptop via USB cable and I can copy books. I can also send books to &lt;a href="http://www.amazon.com/gp/sendtokindle/email" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;kindle via email&lt;/a&gt;.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I found an &lt;a href="https://ifttt.com/recipes/168186-drop-ebooks-and-documents-into-dropbox-folder-to-send-to-kindle-via-gmail-as-azw-ebook" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;IFTTT recipe&lt;/a&gt;, to automate all this process. I just need to create a folder to store all the books in dropbox. Then use IFTTT recipe to link dropbox folder which has books and gmail to send books to kindle email.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Now when I move required books into dropbox folder in my laptop, they will automatically appear in my kinde.&lt;/div&gt;&lt;/div&gt;</description><category>automation</category><category>books</category><guid>https://avilpage.com/2016/02/auto-convert-upload-books-to-kindle.html</guid><pubDate>Sun, 28 Feb 2016 10:32:00 GMT</pubDate></item><item><title>Automate Boring Stuff - Accepting Waitlist RSVPs</title><link>https://avilpage.com/2016/02/automate-boring-stuff-accepting.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;a href="http://www.meetup.com/" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;Meetup.com&lt;/a&gt; makes it easier to organize events. Before meetup you can specify how many people you can accomodate. Then you send mail to all people so that interested people can RSVP.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;If RSVP is full, people can join waitlist. So if somebody changes &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;RSVP&lt;/code&gt; to &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;No&lt;/code&gt;, we can accomodate people in waitlist.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;On the otherhand, if you find a place where you can accomodate more number than you have planned, you can accept all people in waitlist.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Unfortunately, there is no option in meetup for that. You have to accept people one by one which is a boring job if there are ~50 people in waitlist.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;This where Python comes to rescue. Python has an excellent package called &lt;a href="https://github.com/asweigart/pyautogui" style="box-sizing: border-box; color: #4078c0; cursor: pointer; text-decoration: none;"&gt;pyautogui&lt;/a&gt; which helps you to automate all boring tasks.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Here is the simple script I have used for this task.&lt;/div&gt;&lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; time&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; pyautogui&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;print&lt;/span&gt;(&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;Goto meetup event page and place cursor...&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;time.sleep(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;5&lt;/span&gt;)&lt;br&gt;&lt;br&gt;x, y &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; pyautogui.position()&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;for&lt;/span&gt; i &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;range&lt;/span&gt;(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;100&lt;/span&gt;):&lt;br&gt;    pyautogui.click(x, y)&lt;br&gt;    time.sleep(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;5&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;The code is self explanatory. First we are importing &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;pyautogui&lt;/code&gt; and then wait for 5 seconds so that we can go to meetup page and point mouse correctly. Get the cursor position and start clicking on that position with a gap of 5 seconds. This gap is needed as meetup shows a notification once you accept  &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;RSVP&lt;/code&gt;.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Pyautogui is an interesting package which makes your boring job easier.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;div style="box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;strong style="box-sizing: border-box;"&gt;Update:&lt;/strong&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; line-height: 25.6px; margin-bottom: 16px;"&gt;Just found that increasing &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Attendee limit&lt;/code&gt; auto changes RSVP of waitlist people to &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Yes&lt;/code&gt;.&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;span style='background-color: white; color: #666666; font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif; font-size: 16.8px; line-height: 20.16px;'&gt;Read more &lt;/span&gt;&lt;a href="http://www.avilpage.com/search/label/python" style="background-color: white; color: #5421bb; cursor: pointer; font-family: 'trebuchet ms', trebuchet, verdana, sans-serif; font-size: 16.8px; line-height: 20.16px; text-decoration: none;"&gt;articles about Python&lt;/a&gt;&lt;span style='background-color: white; color: #666666; font-family: "trebuchet ms" , "trebuchet" , "verdana" , sans-serif; font-size: 16.8px; line-height: 20.16px;'&gt;!&lt;/span&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#code-highlighting-in-blog-posts" id="user-content-code-highlighting-in-blog-posts" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;</description><category>python</category><category>tech</category><guid>https://avilpage.com/2016/02/automate-boring-stuff-accepting.html</guid><pubDate>Mon, 01 Feb 2016 11:26:00 GMT</pubDate></item><item><title>Dropbox As Wormhole Between Ubuntu &amp; Google Drive!</title><link>https://avilpage.com/2015/12/dropbox-as-wormhole-between-ubuntu.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I use Ubuntu on multiple computers everyday. It is important to keep various files synced across them. I keep most of the public data in github repositories and it is very easy to sync across multiple machines.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;a href="https://drive.google.com/" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;Google Drive&lt;/a&gt; gives 15GB of space with free account. I have multiple accounts and that space is enough to backup my data. I have been storing lots of files in Google Drive from past few years. The main problem is that Google Drive doesn't have a Linux client. To add files, I need to open a web page and then select files to upload and wait until its done. There are few 3rd party clients and none of them work well. So, it is very difficult to sync them across multiple computers.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;a href="https://dropbox.com/" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;Dropbox&lt;/a&gt; gives 5GB of space with free account. It has Linux client and it works very well. But 5GB of space is not sufficient to store my data.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;It is quite difficult to pick one among them as I need benefits of both for free.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Even though I have lot of data, I dont want all of it to sync to all computers everyday. Nearly 90% of data is just backup. Only 10% of data needs to be synced between multiple computers. So I decided to use dropbox as a frontend to google drive.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I have created 2 folders, say &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Daily&lt;/code&gt; &amp;amp; &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Backup&lt;/code&gt; in Dropbox.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Whatever I add to &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Daily&lt;/code&gt; folder will be in Dropbox and it will sync across multiple machines.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;There is an amazing service called &lt;a href="https://ifttt.com/wtf" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;IFTTT&lt;/a&gt; which will help you to connect two products/apps. I found a &lt;a href="https://ifttt.com/recipes/54687-sync-new-files-added-to-dropbox-to-google-drive" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;IFTTT recipe&lt;/a&gt; which will add dropbox files in one folder to Google drive.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I have connected &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Backup&lt;/code&gt; folder in Dropbox to Google Drive. Whenever I add a file to &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Backup&lt;/code&gt; folder in Dropbox, it gets added to Google Drive. O&lt;span style="line-height: 25.6px;"&gt;nce in a week, I will delete files in &lt;/span&gt;&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Backup&lt;/code&gt;&lt;span style="line-height: 25.6px;"&gt; directory so that Dropbox won't run out of space. So &lt;/span&gt;&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Backup&lt;/code&gt;&lt;span style="line-height: 25.6px;"&gt; folder will serve as a wormhole to transfer files into &lt;/span&gt;&lt;span style="line-height: 25.6px;"&gt;Google Drive from my system.&lt;/span&gt;&lt;br&gt;&lt;span style="line-height: 25.6px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="line-height: 25.6px;"&gt;Since I have multiple Google accounts, I have created multiple folders in Dropbox and all folders will be synced to corresponding Google Drive folders.&lt;/span&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;This setup works well for me as I have Dropbox's Linux client and sufficient storage to backup data to Google Drive.&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>tech</category><guid>https://avilpage.com/2015/12/dropbox-as-wormhole-between-ubuntu.html</guid><pubDate>Mon, 21 Dec 2015 11:13:00 GMT</pubDate></item><item><title>Book Review - A Psycho Path By Haris Ibrahim K. V.</title><link>https://avilpage.com/2015/11/book-review-pyscho-path-by-haris.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I stumbled on haris blog and I am thrilled to find that he wrote a book called &lt;a href="https://sosaysharis.wordpress.com/the-psycho-book/" target="_blank"&gt;A Psycho Path&lt;/a&gt;. Since ebook was free, I downloaded it and started reading.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I skipped &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Foreward&lt;/code&gt;, &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Preface&lt;/code&gt; and skimmed through the first story &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Etsuko’s picnic&lt;/code&gt;.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;The second story in the book is &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;A surprising blood test&lt;/code&gt;. The story is quite impressive and it hooked me in. Before that story I was lying on the bed and reading. After reading it I got up, sat properly and started reading. Among all the stories, I liked it the most.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Sound relations&lt;/code&gt; is another article which I found very fascinating. I read the article many times... 10 times? 20 times? may be more. Long before reading the book, me &amp;amp; my friends had a similar discussion while discussing about impact of music. This article gave an interesting conclusion to our discussion.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Narration of &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Quito San&lt;/code&gt; is interesting.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;The book has ~20 stories/articles. Most stories are short stories(2-4 pages). &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;The Prophecy of Amelyah&lt;/code&gt; and &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Quito San&lt;/code&gt; are medium sized stories(~20 pages).&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Overall the book is very good.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;I got a print book after reading ebook. I would recommend getting a get print book from &lt;a href="http://pothi.com/pothi/book/haris-ibrahim-k-v-psycho-path" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;Pothi&lt;/a&gt; or &lt;a href="http://www.amazon.in/s/ref=nb_sb_noss?url=me%3DA1F25HUQJ2HQZO&amp;amp;field-keywords=psycho+path" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;Amazon&lt;/a&gt;. You can also download &lt;a href="https://github.com/harisibrahimkv/psycho-book/blob/master/book.pdf?raw=true" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;free ebook here&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;</description><category>books</category><guid>https://avilpage.com/2015/11/book-review-pyscho-path-by-haris.html</guid><pubDate>Tue, 17 Nov 2015 10:50:00 GMT</pubDate></item><item><title>PyCon India 2015 - First PyCon Experience!</title><link>https://avilpage.com/2015/10/pycon-india-2015-first-pycon-experience.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;a href="https://in.pycon.org/2015/" target="_blank"&gt;PyCon India&lt;/a&gt; 2015 was my first PyCon as an attendee, speaker &amp;amp; volunteer.&lt;br&gt;&lt;br&gt;When I first heard about PyCon in BangPypers meetup, I thought PyCon India is just like a big meetup with a little bit of planning &amp;amp; preparation. But by the end of conference, I have realised that organising PyCon is a very very huge task. It needs a great deal of preparation, planning up things and dedicated volunteers who are interested and patient enough to spend lots of time to run it.&lt;br&gt;&lt;br&gt;Nicholas Tollervey was keynote speaker. He came to venue on October 1st(two days before conference) and helped volunteers with some tasks. He did the same on next day too. I was wondering whether he came for key note speaking or volunteering.&lt;br&gt;&lt;br&gt;I have been talking to many people on mailing lists, github and other channels. Finally I was able to meet &amp;amp; talk with many of them in person.&lt;br&gt;&lt;br&gt;I was not able to attend all sessions but many people said this&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-9VgVTNHxKdw/VhLOzxutSmI/AAAAAAAAN0U/UZO2IrVkYZI/s1600/pycon-india.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="152" src="http://2.bp.blogspot.com/-9VgVTNHxKdw/VhLOzxutSmI/AAAAAAAAN0U/UZO2IrVkYZI/s640/pycon-india.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;It was good to see some of 2nd &amp;amp; 3rd year B.Tech students, who were familiar with django &amp;amp; were contributing to many upstream packages. Some students were even using Emacs as their editor.&lt;br&gt;&lt;br&gt;Toddlers were also interested to attend PyCon&lt;br&gt;&lt;a href="http://2.bp.blogspot.com/-9qfufBcoa4Y/VhLO1qsFV3I/AAAAAAAAN0c/sHYWrL7h6kc/s1600/pycon-india2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="111" src="http://2.bp.blogspot.com/-9qfufBcoa4Y/VhLO1qsFV3I/AAAAAAAAN0c/sHYWrL7h6kc/s640/pycon-india2.png" width="640"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;I have planned to make Python logo mosaic with rubik cubes. I thought it will take ~10 hours to complete it. When I got there with cubes, Vignesh U, Apoorva, Ram Mohan, Sayan Chowday and many other volunteers came forward and completed it in an hour.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-4g9ourILjdA/VhLO3T1XwwI/AAAAAAAAN0k/BJGcFDMALiQ/s1600/rubik-cube-python.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="546" src="http://2.bp.blogspot.com/-4g9ourILjdA/VhLO3T1XwwI/AAAAAAAAN0k/BJGcFDMALiQ/s640/rubik-cube-python.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;I was eagerly waiting for PyCon India from past few months. PyCon India was just like a cool breeze! Ah...!!&lt;br&gt;&lt;br&gt;&lt;b&gt;Update:&lt;/b&gt;&lt;br&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;How the hell did I forget about swag kit marathon?&lt;br&gt;&lt;br&gt;Day before conference, we had to prepare swag kits for participants. I don't know whose idea it was to prepare it like this, that but it was brilliant and most fun part.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/Ejr6iqqCdhc/0.jpg" frameborder="0" height="350" src="https://www.youtube.com/embed/Ejr6iqqCdhc?feature=player_embedded" width="650"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>python</category><category>rubiks-cube</category><guid>https://avilpage.com/2015/10/pycon-india-2015-first-pycon-experience.html</guid><pubDate>Mon, 05 Oct 2015 14:03:00 GMT</pubDate></item><item><title>Set Emacs As Default File Manager In Ubuntu!</title><link>https://avilpage.com/2015/09/set-emacs-as-default-file-manager-in.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;In this post, lets see how to do this&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-PTw-ItpGj98/VfBVVHE1WrI/AAAAAAAANzo/OkVM41veZgs/s1600/emacs-file-manager2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="358" src="http://1.bp.blogspot.com/-PTw-ItpGj98/VfBVVHE1WrI/AAAAAAAANzo/OkVM41veZgs/s640/emacs-file-manager2.gif" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;br&gt;I am using Ubuntu and it has nautilus as default file manager. You might need to use some other commands based on your OS.&lt;/div&gt;&lt;h3 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px; text-align: left;"&gt;File Manager:&lt;/h3&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;If you are in terminal, to open file manager, you need to run &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;nautilus&lt;/code&gt;. If you want to open file manager in specific folder, you can run &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;nautilus /foo/bar&lt;/code&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;When you have downloaded some files using browser, if you click &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;Show in folder&lt;/code&gt; in downloads page, it will open nautilus with that specific folder.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;We can also make Emacs to act as file manager in dired mode. If you run&lt;/div&gt;&lt;div class="highlight highlight-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;$ emacs -q --eval &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;(dired "~")&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;In terminal, emacs starts with a dired buffer for loggined user home directory.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Now lets write a small bash script to do the same thing.&lt;/div&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-stretch: normal; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;&lt;span class="pl-c" style="box-sizing: border-box;"&gt;&lt;span style="background-color: #fcfcf7;"&gt;&lt;span style="color: #222222; font-family: monospace, monospace;"&gt;&lt;span style="font-size: 14px; line-height: 20px;"&gt;#!/bin/bash&lt;br&gt; #!/usr/bin/bash&lt;br&gt; if [ $# -gt 0 ]; then&lt;br&gt;     dirname=$1&lt;br&gt; else&lt;br&gt;     dirname=$HOME&lt;br&gt; fi&lt;br&gt; emacsclient -c -eval "(dired \"$dirname\")" &amp;gt; /dev/null&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Save this file as &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;emacsfm&lt;/code&gt; in &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;/usr/local/bin&lt;/code&gt;. Now you can run &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;emacsfm&lt;/code&gt; in terminal which open home dired buffer or you can run &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;emacsfm /foo/bar&lt;/code&gt; which will open &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;/foo/bar&lt;/code&gt; dired buffer.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Now lets set, &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;emacsfm&lt;/code&gt; as default file manager. For that first we need to install &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;exo-utils&lt;/code&gt;.&lt;/div&gt;&lt;div class="highlight highlight-sh" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;$ sudo apt-get install exo-utils&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;and run it&lt;/div&gt;&lt;div class="highlight highlight-sh" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;$ exo-preferred-applications&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;It opens a new window like this.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;Go to &lt;strong style="box-sizing: border-box;"&gt;Utilities&lt;/strong&gt; -&amp;gt; &lt;strong style="box-sizing: border-box;"&gt;File manager&lt;/strong&gt;, select &lt;strong style="box-sizing: border-box;"&gt;Other&lt;/strong&gt; and goto &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;/usr/local/bin&lt;/code&gt; and select &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;emacsfm&lt;/code&gt; from it.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"&gt;Now if you go to browser downloads and click on &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; margin: 0px; padding: 0.2em 0px;"&gt;show in folder&lt;/code&gt;, it will emacs dired.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"&gt;&lt;b&gt;References:&lt;/b&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box;"&gt;&lt;span style="color: #333333; font-family: Helvetica Neue, Helvetica, Segoe UI, Arial, freesans, sans-serif;"&gt;&lt;span style="line-height: 25.6px;"&gt;&lt;a href="https://help.ubuntu.com/community/DefaultFileManager"&gt;https://help.ubuntu.com/community/DefaultFileManager&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box;"&gt;&lt;span style="color: #333333; font-family: Helvetica Neue, Helvetica, Segoe UI, Arial, freesans, sans-serif;"&gt;&lt;span style="line-height: 25.6px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box;"&gt;&lt;br class="Apple-interchange-newline"&gt;&lt;span style="background-color: white; color: #5421bb; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.8px; line-height: 20.16px;"&gt;&lt;a href="http://www.avilpage.com/search/label/emacs"&gt;More articles about Emacs&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</description><category>emacs</category><category>tech</category><guid>https://avilpage.com/2015/09/set-emacs-as-default-file-manager-in.html</guid><pubDate>Tue, 08 Sep 2015 12:42:00 GMT</pubDate></item><item><title>[Python] Functions, Methods &amp; Attributes!</title><link>https://avilpage.com/2015/09/python-functions-methods-attributes.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;First, lets take a look at functions &amp;amp; methods and then define attributes for them.&lt;/div&gt;&lt;h2 style="border-bottom-color: rgb(238, 238, 238); border-bottom-style: solid; border-bottom-width: 1px; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.75em; line-height: 1.225; margin-bottom: 16px; margin-top: 1em; padding-bottom: 0.3em; position: relative;"&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#functions-vs-methods" id="user-content-functions-vs-methods" style="box-sizing: border-box; color: #4078c0; display: block; left: 0px; line-height: 1; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;Functions Vs Methods:&lt;/h2&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;]: &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; f():&lt;br&gt;   ...:     &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;pass&lt;/span&gt;&lt;br&gt;   ...: &lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;]: &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;class&lt;/span&gt; C:&lt;br&gt;   ...:     &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; m(&lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;self&lt;/span&gt;):&lt;br&gt;   ...:         &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;pass&lt;/span&gt;&lt;br&gt;   ...:&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;We have just defined a function and a class(with a method in it).&lt;/div&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;18&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;type&lt;/span&gt;(f)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;18&lt;/span&gt;]: function&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;19&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;type&lt;/span&gt;(C.m)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;19&lt;/span&gt;]: function&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;20&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;type&lt;/span&gt;(C().m)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;20&lt;/span&gt;]: method&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;21&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;set&lt;/span&gt;(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;dir&lt;/span&gt;(C().m)) &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;set&lt;/span&gt;(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;dir&lt;/span&gt;(f))&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;21&lt;/span&gt;]: {&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;__func__&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;__self__&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;}&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;As seen above, a function binded to an instance of a class is method and an unbound method is a just a function. Also a method has &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__self__&lt;/code&gt; and &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__func__&lt;/code&gt; attributes in addition attributes of a function.&lt;/div&gt;&lt;h2 style="border-bottom-color: rgb(238, 238, 238); border-bottom-style: solid; border-bottom-width: 1px; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.75em; line-height: 1.225; margin-bottom: 16px; margin-top: 1em; padding-bottom: 0.3em; position: relative;"&gt;&lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#attributes" id="user-content-attributes" style="box-sizing: border-box; color: #4078c0; display: block; left: 0px; line-height: 1; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;"&gt;&lt;/a&gt;Attributes:&lt;/h2&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Lets add some attributes to function &amp;amp; method and see how they work.&lt;/div&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;21&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;setattr&lt;/span&gt;(f, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;)&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;22&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;hasattr&lt;/span&gt;(f, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;22&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;True&lt;/span&gt;&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;24&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;getattr&lt;/span&gt;(f, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;24&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;We can do the same thing with unbound method(which is nothing but a function) also&lt;/div&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;31&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;setattr&lt;/span&gt;(C.m, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;)&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;32&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;hasattr&lt;/span&gt;(C.m, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;32&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;True&lt;/span&gt;&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;33&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;getattr&lt;/span&gt;(C.m, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;33&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;But we cant do the same thing with bound methods.&lt;/div&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;34&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;setattr&lt;/span&gt;(C().m, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;)&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;---------------------------------------------------------------------------&lt;/span&gt;&lt;br&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;AttributeError&lt;/span&gt;                            Traceback (most recent call last)&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;ipython&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;input&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;34&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1379e94&lt;/span&gt;f2f48&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;module&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt;()&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;----&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;setattr&lt;/span&gt;(C().m, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;AttributeError&lt;/span&gt;: &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;method&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;object&lt;/span&gt; has no attribute &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;When users add attributes to a function, they are stored in its &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__dict__&lt;/code&gt; attribute.&lt;/div&gt;&lt;pre lang="python3" style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;In [40]: f.__dict__&lt;br&gt;Out[40]: {'state': 1}&lt;br&gt;&lt;br&gt;In [49]: C.m.__dict__&lt;br&gt;Out[49]: {'state': 2}&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;As we have seen in the beginning, method objects just hold reference to its class(&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__self__&lt;/code&gt;) and function(&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__func__&lt;/code&gt;). But they don't have its own &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__dict__&lt;/code&gt; to hold custom attributes. So we cannot set custom attributes to instance methods.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;But we can get the function that is referenced by bound method and set attribute for it.&lt;/div&gt;&lt;div class="highlight highlight-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;36&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;setattr&lt;/span&gt;(C().m.&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;__func__&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;)&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;39&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;getattr&lt;/span&gt;(C().m.&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;__func__&lt;/span&gt;, &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;state&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;39&lt;/span&gt;]: &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Also methods provide, special &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;__getattr__&lt;/code&gt; which forwards attribute access to function object. So, this will work&lt;/div&gt;&lt;pre lang="python3" style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;In [52]: hasattr(C().m, 'state')&lt;br&gt;Out[52]: True&lt;br&gt;&lt;br&gt;In [53]: getattr(C().m, 'state')&lt;br&gt;Out[53]: 3&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"&gt;So we can just set attributes to functions &amp;amp; unbound methods just like classes but we can't do it for bound methods.&lt;/div&gt;&lt;/div&gt;</description><category>python</category><category>tech</category><guid>https://avilpage.com/2015/09/python-functions-methods-attributes.html</guid><pubDate>Tue, 01 Sep 2015 14:17:00 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #5 - Use for...empty in Django templates</title><link>https://avilpage.com/2015/08/use-for-empty-in-django-templates.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;It is quite common to send a query set from a view to template, loop over it and display items in it. If no items are there, it is good if we display some message. For that we can do something like this.&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;{% if books %}&lt;br&gt;  {% for book in books %}&lt;br&gt;    &amp;lt;li&amp;gt;{{ book }}&amp;lt;/li&amp;gt;&lt;br&gt;  {% endfor %}&lt;br&gt;{% else %}&lt;br&gt;  &amp;lt;li&amp;gt;Sorry, there are no books.&amp;lt;/li&amp;gt;&lt;br&gt;{% endif %}&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Django &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;{% for %}&lt;/code&gt; tag takes an optional &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;{% empty %}&lt;/code&gt; clause which will be rendered when queryset is empty. So we can rewrite the above code as&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;{% for book in books %}&lt;br&gt;  &amp;lt;li&amp;gt;{{ book }}&amp;lt;/li&amp;gt;&lt;br&gt;{% empty %}&lt;br&gt;  &amp;lt;li&amp;gt;Sorry, there are no books.&amp;lt;/li&amp;gt;&lt;br&gt;{% endfor %}&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;This code is much cleaner than previous one. I tried to profile both code blocks. The first block took 0.9ms and second block took 0.8ms which means it is 11% faster than previous code :)&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Reference: &lt;a href="https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#for-empty" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;Django docs&lt;/a&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2015/08/use-for-empty-in-django-templates.html</guid><pubDate>Tue, 04 Aug 2015 12:16:00 GMT</pubDate></item><item><title>Random Life Quotes #2</title><link>https://avilpage.com/2015/07/random-life-quotes-2.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-AzGVbSZJeLk/VbUNJHVpzYI/AAAAAAAANyo/5JP2qAnvhgU/s1600/life-quotes911.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/-AzGVbSZJeLk/VbUNJHVpzYI/AAAAAAAANyo/5JP2qAnvhgU/s640/life-quotes911.png" width="608"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-gGoWqgx6Gh0/VbUNEpLh4nI/AAAAAAAANxw/JsRH5CUnM94/s1600/life-quotes-45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-gGoWqgx6Gh0/VbUNEpLh4nI/AAAAAAAANxw/JsRH5CUnM94/s640/life-quotes-45.png" width="612"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-pf1d2FXaKpI/VbUNE7QRYqI/AAAAAAAANx4/-DaK95WenIs/s1600/life-quotes-88.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-pf1d2FXaKpI/VbUNE7QRYqI/AAAAAAAANx4/-DaK95WenIs/s640/life-quotes-88.png" width="626"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-wHXr8M1kHFI/VbUNGT_92lI/AAAAAAAANyI/0zpEKQmubYs/s1600/life-quotes-92.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-wHXr8M1kHFI/VbUNGT_92lI/AAAAAAAANyI/0zpEKQmubYs/s640/life-quotes-92.png" width="604"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-JmOogat0HKg/VbUNHYVo3uI/AAAAAAAANyQ/GbzNR7DeT7k/s1600/life-quotes-93.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-JmOogat0HKg/VbUNHYVo3uI/AAAAAAAANyQ/GbzNR7DeT7k/s640/life-quotes-93.png" width="612"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-WoT8doyVGvI/VbUNDDT3EfI/AAAAAAAANxc/x1uiAwuVgKE/s1600/life-quotes-190.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-WoT8doyVGvI/VbUNDDT3EfI/AAAAAAAANxc/x1uiAwuVgKE/s640/life-quotes-190.png" width="610"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-uJkEvS3t65c/VbUNDH-W3aI/AAAAAAAANxY/RX3Vvjkxm44/s1600/life-quotes-221.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-uJkEvS3t65c/VbUNDH-W3aI/AAAAAAAANxY/RX3Vvjkxm44/s640/life-quotes-221.png" width="612"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ZyBXbIB7TqQ/VbUNIYosoGI/AAAAAAAANyY/G_0T-4L3qgc/s1600/life-quotes221.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="220" src="http://4.bp.blogspot.com/-ZyBXbIB7TqQ/VbUNIYosoGI/AAAAAAAANyY/G_0T-4L3qgc/s640/life-quotes221.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;
    &lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/--akodPewVv0/VbUNDlVbchI/AAAAAAAANxg/GbApyJNW-nU/s1600/life-quotes-333.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/--akodPewVv0/VbUNDlVbchI/AAAAAAAANxg/GbApyJNW-nU/s640/life-quotes-333.png" width="622"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-hgjAr3S3jl0/VbUNEX2qY_I/AAAAAAAANx0/SGghUIN3xCw/s1600/life-quotes-334.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-hgjAr3S3jl0/VbUNEX2qY_I/AAAAAAAANx0/SGghUIN3xCw/s640/life-quotes-334.png" width="614"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-GHU8wv2o0u4/VbUNBa1whxI/AAAAAAAANxQ/fw-vt7o_1mo/s1600/life-quotes-1199.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="http://1.bp.blogspot.com/-GHU8wv2o0u4/VbUNBa1whxI/AAAAAAAANxQ/fw-vt7o_1mo/s640/life-quotes-1199.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-kFbBifzqBvo/VbUNH_YY5kI/AAAAAAAANyU/WmMXoTW7R8g/s1600/life-quotes-9921.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="130" src="http://3.bp.blogspot.com/-kFbBifzqBvo/VbUNH_YY5kI/AAAAAAAANyU/WmMXoTW7R8g/s640/life-quotes-9921.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
    &lt;/div&gt;</description><category>quotes</category><guid>https://avilpage.com/2015/07/random-life-quotes-2.html</guid><pubDate>Sun, 26 Jul 2015 11:13:00 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #4 - Make Django Development Server Persistent</title><link>https://avilpage.com/2015/07/django-tips-make-django-development.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;I use Emacs for writing Python code. I also use &lt;a href="https://github.com/ChillarAnand/real-auto-save" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;real-auto-save&lt;/a&gt; to save my files after 10 seconds of inactivity.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;While coding, when I stop writing in the middle, after 10 seconds Emacs auto saves the file. Django recognizes this &amp;amp; reloads the development server.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Once I complete writing code, I go to browser &amp;amp; refresh the page. Since the code I was writing was incomplete somewhere in the middle and had some errors, Django development server was stopped and page won't reload. Now I have to go back to terminal and restart the server and again go back to browser to refresh page.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;To overcome this, Django server must be made persistent. The easiest way to accomplish this is to use a &lt;a href="http://stackoverflow.com/questions/25199550/auto-restart-django-development-server-on-file-save-after-previous-error" style="box-sizing: border-box; color: #4078c0; text-decoration: none;"&gt;simple bash script as described here&lt;/a&gt;.&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;$ while true; do python manage.py runserver; sleep 4; done&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;When Django development server stops, after 4 seconds it tries to start automatically and goes on forever.&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Instead of typing that everytime, it better to write this as a shell script and put it in system path, so that it can be used in any project.&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;while true; do&lt;br&gt;  echo "Re-starting Django runserver"&lt;br&gt;  python manage.py runserver&lt;br&gt;  sleep 4&lt;br&gt;done&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px;"&gt;Save this &amp;amp; make it executable(&lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;chmod +x&lt;/code&gt;), use it is ./filename.sh and to stop use &lt;code style="background-color: rgba(0, 0, 0, 0.0392157); border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin: 0px; padding: 0.2em 0px;"&gt;Ctrl-c Ctrl-c&lt;/code&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2015/07/django-tips-make-django-development.html</guid><pubDate>Mon, 20 Jul 2015 13:11:00 GMT</pubDate></item><item><title>Git Etiquette: Meaningful Messages &amp; Linear Logs!</title><link>https://avilpage.com/2015/06/git-etiquette-meaningful-messages.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h3 style="text-align: left;"&gt;Why Elegant Git Logs Matter?&lt;/h3&gt;I will show You few commit messages &amp;amp; logs from two different projects. Based only on those messages/logs, You need to decide which project is the best.&lt;br&gt;&lt;br&gt;&lt;h4 style="text-align: left;"&gt;Project 1:&lt;/h4&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-B6ywHekOKj8/VYGjD0HcA0I/AAAAAAAANwc/HzOOlPQRDuo/s1600/git-log8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="552" src="http://2.bp.blogspot.com/-B6ywHekOKj8/VYGjD0HcA0I/AAAAAAAANwc/HzOOlPQRDuo/s640/git-log8.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-oBfd3GDwnU8/VYGjDFVOxgI/AAAAAAAANwQ/5Kooota69H8/s1600/git-log4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="339" src="http://3.bp.blogspot.com/-oBfd3GDwnU8/VYGjDFVOxgI/AAAAAAAANwQ/5Kooota69H8/s640/git-log4.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;h4 style="text-align: left;"&gt;Project 2:&lt;/h4&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-P1J1lUyA0No/VYGjEC-jn1I/AAAAAAAANwg/_aCRJamsfdA/s1600/git-log9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="496" src="http://3.bp.blogspot.com/-P1J1lUyA0No/VYGjEC-jn1I/AAAAAAAANwg/_aCRJamsfdA/s640/git-log9.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-V9Mo7qYzqzM/VYGjD8z6vXI/AAAAAAAANwY/T4mxPsj51XA/s1600/git-log6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="318" src="http://2.bp.blogspot.com/-V9Mo7qYzqzM/VYGjD8z6vXI/AAAAAAAANwY/T4mxPsj51XA/s640/git-log6.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;I hope that explains why We need  to maintain elegant git logs.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;How To Maintain Elegant Logs?&lt;/h3&gt;&lt;br&gt;First let's see how to write good commit messages. There are several blog  posts  &amp;amp; guides about this. Here is the summary of all those taken from &lt;a href="http://chris.beams.io/posts/git-commit/" target="_blank"&gt;this article&lt;/a&gt;.&lt;br&gt;&lt;br&gt;1. Separate subject from body with a blank line&lt;br&gt;2. Limit the subject line to 50 characters&lt;br&gt;3. Capitalize the subject line&lt;br&gt;4. Do not end the subject line with a period&lt;br&gt;5. Use the imperative mood in the subject line&lt;br&gt;6. Wrap the body at 72 characters&lt;br&gt;7. Use the body to explain what and why vs. how&lt;br&gt;&lt;br&gt;If You are doing something hacky, writing a little message in commit on why you did that will help other developers to understand that a lot better. Even if You don't follow all rules, some of them will help you in writing great commit message next time. If You are mainainter of a project, ask Your team members to write meaningful messages.&lt;br&gt;&lt;br&gt;The next that need to be taken care is commits. If a team member or someone else has submitted a pull request, once you merge the commit, just rebase it to remove unnecessary merge commits from log. Also make sure to squash  redundant commits and You have almost a linear log.&lt;br&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;A side benefit of this is, You can see recent commit there instead of merge commit, if your project is hosted on github.&lt;br&gt;&lt;br&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nDLmU2DsDhs/VYGjB86NHJI/AAAAAAAANv4/pba4wkAWiMc/s1600/git-log2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="88" src="http://1.bp.blogspot.com/-nDLmU2DsDhs/VYGjB86NHJI/AAAAAAAANv4/pba4wkAWiMc/s400/git-log2.png" width="400"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;The two minutes You spent on writing a meaningful message or maintaining linear log will&lt;br&gt;will help You a  lot few months down the line &amp;amp; will save countless hours and sleepless nights for future contributors.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;Read more &lt;/span&gt;&lt;a href="http://www.avilpage.com/search/label/tech" style="background-color: white; color: #5421bb; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px; text-decoration: none;"&gt;articles about Technology!&lt;/a&gt;&lt;/div&gt;</description><category>git</category><category>tech</category><guid>https://avilpage.com/2015/06/git-etiquette-meaningful-messages.html</guid><pubDate>Wed, 17 Jun 2015 11:29:00 GMT</pubDate></item><item><title>Automatically PEP8 &amp; Format Your Python Code</title><link>https://avilpage.com/2015/05/automatically-pep8-your-python-code.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"&gt;&lt;/script&gt;&lt;script src="//cdnjs.cloudflare.com/ajax/libs/gist-embed/2.1/gist-embed.min.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;Even if you don't intend anybody else to read your code, there's still a very good chance that somebody will have to stare at your code and &lt;br&gt;figure out what it does: That person is probably going to be you, &lt;br&gt;twelve months from now&lt;span style="font-size: xx-small;"&gt;[1]&lt;/span&gt;.&lt;/pre&gt;&lt;/div&gt;or as Zen of Python says "Readability Counts".&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;PEP8 Style Guide:&lt;/h3&gt;Since code is read more than it is written, it is very important to make sure that the code is readable. Python has coding convetions(&lt;a href="https://www.python.org/dev/peps/pep-0008/" target="_blank"&gt;PEP8 style guide&lt;/a&gt;) to maintain consistency in code and thereby making it more readable.&lt;br&gt;&lt;br&gt;There are lot of tools (like &lt;a href="https://github.com/jcrocholl/pep8" target="_blank"&gt;pep8&lt;/a&gt;, &lt;a href="https://pypi.python.org/pypi/flake8" target="_blank"&gt;flake8&lt;/a&gt;, &lt;a href="http://www.pylint.org/" target="_blank"&gt;pylint&lt;/a&gt;) to check if Your code is in compliance with PEP8. Today most of the IDE/text editors have plugins which check for these errors and report it on the fly. If You are writing code from scratch, You can make sure that You are following coding conventions.&lt;br&gt;&lt;br&gt;However once in a while You have to read/bug-fix other people's code who don't follow these conventions(or You might even stumble across Your old piece of code). Once You are accustomed to style guide, it will be uneasy to read inconsistent code. Here is a badly formatted Python file opened in Emacs editor(with flymake &amp;amp; flake8 configured)&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Kzv9OZt3MV0/VWC-mB4cjlI/AAAAAAAANvU/ZvHSC5aaAnw/s1600/auto-pep8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="332" src="http://1.bp.blogspot.com/-Kzv9OZt3MV0/VWC-mB4cjlI/AAAAAAAANvU/ZvHSC5aaAnw/s640/auto-pep8.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;Custom Style Guide:&lt;/h3&gt;If You don't like any of PEP8 rules, You can set Your own style guide for Your project. Most developers find limiting line length to 79 characters annoying. So they set their own line limit. You can even configure PEP8 checkers to take You own guidelines and check the code according to it.&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;Auto PEP8:&lt;/h3&gt;Formatting code to PEP8 style is boring &amp;amp; time consuming process. So instead of manually formatting code, You can use &lt;a href="https://pypi.python.org/pypi/autopep8/" target="_blank"&gt;autopep8&lt;/a&gt; package which automatically formats Python code to conform to the PEP 8 style guide.&lt;br&gt;&lt;br&gt;To install the package run&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;$ &lt;span style="color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px;"&gt;pip install autopep8&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;If You have a file foo.py as show above, You can run&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;$ autopep8 --in-place --aggressive --aggressive foo.py&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both;"&gt;which neatly formats the file like this&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-wMseYjAAsp0/VWC-mHqkLkI/AAAAAAAANvY/hwOow-QGsxc/s1600/auto-pep8-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="561" src="http://1.bp.blogspot.com/-wMseYjAAsp0/VWC-mHqkLkI/AAAAAAAANvY/hwOow-QGsxc/s640/auto-pep8-2.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;Emacs Integration:&lt;/h3&gt;As emacs is extremely configurable editor, with just couple of lines of lisp, we can integrate autopep8 to emacs. Just find where autopep8 is installed; write a function which runs autopep8 on current buffer; bind a key to that function; set a hook, so that when ever You save a file, it will be automatically run the function.&lt;br&gt;&lt;br&gt;&lt;code data-gist-file="autopep8.el" data-gist-hide-footer="true" data-gist-hide-line-numbers="true" data-gist-id="0e8c8351799cdd7254d7"&gt;&lt;/code&gt;This works reasonably well. But I do recommend using &lt;a href="https://github.com/jorgenschaefer/elpy" target="_blank"&gt;Elpy&lt;/a&gt; for Python developemnt in emacs. I have just sent a &lt;a href="https://github.com/jorgenschaefer/elpy/pull/571" target="_blank"&gt;pull request to integrate&lt;/a&gt; autopep8 with elpy.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;Formatting:&lt;/h3&gt;&lt;div&gt;PEP8 formatters like autopep8, pep8ify will remove only lint errors. But they can't beautify code. &lt;/div&gt;&lt;div&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;little = more[3:   5]&lt;br&gt;&lt;br&gt;x = {'a': 37, 'b': 42,&lt;br&gt;     'c': 927}&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Above code remains same after pep8ifying also. But the code doesn't look good yet. You can use formatters like &lt;a href="https://pypi.python.org/pypi/yapf" target="_blank"&gt;yapf&lt;/a&gt;, which will format the code even if the code is PEP8 compliant. &lt;/div&gt;&lt;div&gt;Above code will be formatted to &lt;/div&gt;&lt;div&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;little = more[3:5]&lt;br&gt;&lt;br&gt;x = {'a': 37, 'b': 42, 'c': 927}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Some times this even destroys Your manual formatting. For example &lt;/div&gt;&lt;div&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;BAZ = {&lt;br&gt;    [1, 2, 3, 4],&lt;br&gt;    [5, 6, 7, 8],&lt;br&gt;    [9, 10, 11, 12]&lt;br&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;will be converted to &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;BAZ = {[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;But You can tell it to ignore some parts.&lt;/div&gt;&lt;div&gt;&lt;pre style="border-radius: 3px; border: 1px solid rgb(170, 204, 153); color: #333333; font-family: monospace, sans-serif; font-size: 15.4399995803833px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;BAZ = {&lt;br&gt;    [1, 2, 3, 4],&lt;br&gt;    [5, 6, 7, 8],&lt;br&gt;    [9, 10, 11, 12]&lt;br&gt;}  # yapf: disable&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;Beyond PEP8:&lt;/h3&gt;As we have learnt to auto PEP8 code, it is the time to look beyond PEP8. There is a good talk by Raymond Hettinger on that - &lt;a href="https://www.youtube.com/embed/wf-BqAjZb8M" target="_blank"&gt;Beyond PEP8&lt;/a&gt;, Best practices for beautiful intelligible code.&lt;br&gt;&lt;br&gt;Let Machines take care of PEP8 &amp;amp; Let Humans look Beyond PEP8.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;References:&lt;/h3&gt;[1] &lt;a href="http://blogs.msdn.com/b/oldnewthing/archive/2007/04/06/2036150.aspx" target="_blank"&gt;Code is read much more often than it is written, so plan accordingly&lt;/a&gt;.&lt;br&gt;&lt;a href="https://www.python.org/dev/peps/pep-0008/" target="_blank"&gt;Python - PEP8 style guide&lt;/a&gt;.&lt;br&gt;&lt;a href="https://pypi.python.org/pypi/autopep8/" target="_blank"&gt;Autopep8 - formats Python code to conform to the PEP 8.&lt;/a&gt;&lt;br&gt;&lt;a href="https://pypi.python.org/pypi/pep8ify" target="_blank"&gt;PEP8ify - modifies python source code to conform to PEP8.&lt;/a&gt;&lt;br&gt;&lt;div&gt;&lt;a href="https://pypi.python.org/pypi/yapf" target="_blank"&gt;yapf - A formatter for Python files.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="https://www.youtube.com/embed/wf-BqAjZb8M" target="_blank"&gt;Beyond PEP8 - Best practices for beautiful intelligible code.&lt;/a&gt;&lt;/div&gt;&lt;a href="https://github.com/jorgenschaefer/elpy" target="_blank"&gt;Elpy, the Emacs Lisp Python Environment&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;Read more &lt;/span&gt;&lt;a href="http://www.avilpage.com/search/label/python" style="background-color: white; color: #5421bb; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px; text-decoration: none;"&gt;articles about Python&lt;/a&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;!&lt;/span&gt;&lt;br&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;Read more &lt;/span&gt;&lt;a href="http://www.avilpage.com/search/label/emacs" style="background-color: white; color: #5421bb; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px; text-decoration: none;"&gt;articles about Emacs&lt;/a&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;!&lt;/span&gt;&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>emacs</category><category>python</category><guid>https://avilpage.com/2015/05/automatically-pep8-your-python-code.html</guid><pubDate>Sat, 23 May 2015 13:44:00 GMT</pubDate></item><item><title>Whats So Good About Django Traceback?</title><link>https://avilpage.com/2015/05/whats-so-good-about-django-traceback.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;When You are working on django project, if You make any errors, it will throw a simple traceback on the terminal where you started server.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Qomg2ms9Ij4/VV3m-iGH_uI/AAAAAAAANvA/LT3QzrnMOsg/s1600/django-traceback7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="171" src="http://3.bp.blogspot.com/-Qomg2ms9Ij4/VV3m-iGH_uI/AAAAAAAANvA/LT3QzrnMOsg/s400/django-traceback7.png" width="400"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;If you go to browser, you will find a rich traceback like this.&lt;br&gt;&lt;div style="text-align: center;"&gt;&lt;/div&gt;&lt;div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: center; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px;"&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="-webkit-text-stroke-width: 0px; clear: both; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; orphans: auto; text-align: center; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px;"&gt;&lt;a href="http://2.bp.blogspot.com/-tvh4xHpe3vg/VV3llj9pRjI/AAAAAAAANuc/u4FuL0oQ57A/s1600/django-traceback.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="449" src="http://2.bp.blogspot.com/-tvh4xHpe3vg/VV3llj9pRjI/AAAAAAAANuc/u4FuL0oQ57A/s640/django-traceback.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;Most Python developers, discover django-extensions within a few weeks after they start working with Django and start using Werkzeug debugger. Werkzeug has lot of advantages when compared to default Django traceback. I also used it for a while. For the same error Werkzeug throws traceback like this.&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-GYBZegc7018/VV3lluQru-I/AAAAAAAANuY/rbH5oVZHT2U/s1600/django-traceback4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="420" src="http://3.bp.blogspot.com/-GYBZegc7018/VV3lluQru-I/AAAAAAAANuY/rbH5oVZHT2U/s640/django-traceback4.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;One thing I really like about Django traceback is, the distinction between user code and the internal Django code. Most of the time, developers were looking for the bug in their code instead of looking for a bug in Django. So, Django makes it easier to skip over the frames that doesn't matter and focus on the one which matters most.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ZzMWZjWzo44/VV3moiCWWKI/AAAAAAAANu4/VXHrw1NpA8o/s1600/django-traceback6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="386" src="http://1.bp.blogspot.com/-ZzMWZjWzo44/VV3moiCWWKI/AAAAAAAANu4/VXHrw1NpA8o/s640/django-traceback6.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;It also shows local vars in that frame. With this You instantly look at the variables to find out why error has occured(see this &lt;a href="https://code.djangoproject.com/ticket/11834" target="_blank"&gt;Django Ticket #11834:&lt;/a&gt; for more discussion about this).&lt;br&gt;&lt;br&gt;These two features make it very easy to track down most common errors.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;Read more &lt;/span&gt;&lt;a href="http://www.avilpage.com/search/label/python" style="background-color: white; color: #5421bb; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px; text-decoration: none;"&gt;articles about Python&lt;/a&gt;&lt;span style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 16.7999992370605px; line-height: 20.1599979400635px;"&gt;!&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>django</category><category>python</category><category>tech</category><guid>https://avilpage.com/2015/05/whats-so-good-about-django-traceback.html</guid><pubDate>Thu, 21 May 2015 09:29:00 GMT</pubDate></item><item><title>The Intelligence Behind Python Slices</title><link>https://avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When getting items from a list, if no index is supplied or an invalid index is given, Python throws error.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;---------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="ne"&gt;IndexError&lt;/span&gt;                                &lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ipython&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;b7fb56a1ede&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;----&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="ne"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;ipython-input-6-a17d5cfb2c2f&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="o"&gt;^&lt;/span&gt;
&lt;span class="ne"&gt;SyntaxError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;invalid&lt;/span&gt; &lt;span class="n"&gt;syntax&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When slicing a list, if start/stop/step values are not supplied or invalid values are provided, Python figures out appropriate values and returns relevant items or an empty list depending on the values.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;172&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[:]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;172&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[::]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;174&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;174&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;175&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;176&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;100000000000000000000000000000000000000000000000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;176&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;177&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;177&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;178&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;178&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is something interesting happening with python slicing. Lets see how python slicing works and what happens behind the scenes.&lt;/p&gt;
&lt;h4&gt;Slicing Is NOT Indexing:&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://wiki.python.org/moin/MovingToPythonFromOtherLanguages"&gt;Wiki Python&lt;/a&gt;
has this amazing picture which clearly distinguishes indexing and slicing.&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img alt="python-slicing" src="https://avilpage.com/python-slicing.png"&gt;
&lt;/p&gt;

&lt;p&gt;It is a list with 6 elements in it. To understand slicing better, consider that list as a set of six boxes placed together. Each box has an alphabet in it.&lt;/p&gt;
&lt;p&gt;Indexing is like dealing with the contents of box. You can check
contents of any box. But You can't check contents of multiple boxes at
once. You can even replace contents of the box. But You can't place 2
balls in 1 box or replace 2 balls at a time.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;124&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;124&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;127&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'A'&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;129&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;---------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="ne"&gt;TypeError&lt;/span&gt;                                 &lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ipython&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;129&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c7eb16585371&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;----&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;integers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Slicing is like dealing with boxes itself. You can pickup first box and
place it on another table. To pickup the box all You need to know is the
position of beginning &amp;amp; ending of the box.&lt;/p&gt;
&lt;p&gt;You can even pickup first 3 boxes or last 2 boxes or all boxes between 1
&amp;amp; 4. So, You can pick any set of boxes if You know beginning &amp;amp; ending.
This positions are called start &amp;amp; stop positions.&lt;/p&gt;
&lt;p&gt;The interesting thing is that You can replace multiple boxes at once.
Also You can place multiple boxes where ever You like.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;132&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;133&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;135&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'xx'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;136&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;136&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'xx'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Slicing With Step:&lt;/h4&gt;
&lt;p&gt;Till now You have picked boxes continuously. But some times You need to
pickup discretely. For example You can pickup every second box. You can
even pickup every third box from the end. This value is called step
size. This represents the gap between Your successive pickups. The step
size should be positive if You are picking boxes from the beginning to
end and vice versa.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;143&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;143&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;145&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;145&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;How Python Figures Out Missing Parameters:&lt;/h4&gt;
&lt;p&gt;When slicing if You leave out any parameter, Python tries to figure it
out automatically.&lt;/p&gt;
&lt;p&gt;If You check source code of CPython, You will find a function called
&lt;a href="https://github.com/python/cpython/blob/f7bfa54898598a0da46fdb1e0436d5f9e04c9007/Objects/sliceobject.c#L192"&gt;PySlice_GetIndicesEx&lt;/a&gt; which
figures out indices to a slice for any given parameters. Here is the
logical equivalent code in Python.&lt;/p&gt;
&lt;p&gt;This function takes a Python object &amp;amp; optional parameters for slicing
and returns start, stop, step &amp;amp; slice length for the requested slice.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;py_slice_get_indices_ex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Step cannot be zero."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;slice_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;slice_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;slice_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slice_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the intelligence that is present behind slices. Since Python has inbuilt function called slice, You can pass some parameters &amp;amp; check how smartly it calculates missing parameters.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is how Python is able to figure out missing parameters from slices.&lt;/p&gt;
&lt;p&gt;I started digging this after attending a talk by &lt;a href="https://twitter.com/skeptichacker"&gt;Anand B. Pillai&lt;/a&gt; on python gotchas. Thanks to Anand B. Pillai &amp;amp; Krace Kumar for conducting BangPypers meetup &amp;amp; encouraging to checkout Python source code.&lt;/p&gt;
&lt;h4&gt;References:&lt;/h4&gt;
&lt;p&gt;Wiki Python: &lt;a href="https://wiki.python.org/moin/"&gt;https://wiki.python.org/moin/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;CPython repo: &lt;a href="https://github.com/python/cpython"&gt;https://github.com/python/cpython&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Slice on SO: &lt;a href="http://stackoverflow.com/questions/509211/explain-pythons-slice-notation"&gt;http://stackoverflow.com/questions/509211/explain-pythons-slice-notation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Docs for slice: &lt;a href="https://docs.python.org/3.4/library/functions.html#slice"&gt;https://docs.python.org/3.4/library/functions.html#slice&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Python/C API for slice: &lt;a href="https://docs.python.org/3.4/c-api/slice.html"&gt;https://docs.python.org/3.4/c-api/slice.html&lt;/a&gt;&lt;/p&gt;</description><category>featured</category><guid>https://avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html</guid><pubDate>Sun, 22 Mar 2015 10:31:00 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #3 - Dynamic Initial Values In Forms</title><link>https://avilpage.com/2015/03/django-form-gotchas-dynamic-initial.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Django form fields accept initial argument. So You can set a default value for
a field.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;SampleForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'avil page'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SampleForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_p&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;p&amp;gt;Name: &amp;lt;input maxlength="10" name="name" type="text" value="avil page" /&amp;gt;&amp;lt;/p&amp;gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Sometimes it is required to override &lt;strong&gt;init&lt;/strong&gt; method in forms and set field
initial arguments.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;AdvancedForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="s1"&gt;'override'&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AdvancedForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_p&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;p&amp;gt;Name: &amp;lt;input maxlength="10" name="name" type="text" value="override" /&amp;gt;&amp;lt;/p&amp;gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Now let's pass some initial data to form and see what happens.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;AdvancedForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'override'&lt;/span&gt;  &lt;span class="c1"&gt;# don't try this at home&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AdvancedForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'precedence'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_p&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;p&amp;gt;Name: &amp;lt;input maxlength="10" name="name" type="text" value="precedence" /&amp;gt;&amp;lt;/p&amp;gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If You look at the value of input field, it's is NOT the overrided. It
still has form initial value!&lt;/p&gt;
&lt;p&gt;If You look into &lt;a href="https://github.com/django/django/blob/master/django/forms/forms.py#L631-L633"&gt;source code of django forms&lt;/a&gt; to find what is happening, You will find this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bound_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# precedence matters!!!!&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So form's initial value has precedence over fields initial values.&lt;/p&gt;
&lt;p&gt;So You have to override form's initial value instead of fields's initial value
to make it work as expected.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;AdvancedForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'override'&lt;/span&gt;  &lt;span class="c1"&gt;# aha!!!!&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AdvancedForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'precedence'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;f4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_p&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;p&amp;gt;Name: &amp;lt;input maxlength="10" name="name" type="text" value="override" /&amp;gt;&amp;lt;/p&amp;gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Read official docs about &lt;a href="https://docs.djangoproject.com/en/1.7/ref/forms/api/"&gt;django forms&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read more &lt;a href="https://avilpage.com/search/label/python"&gt;articles about Python&lt;/a&gt;!&lt;/p&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2015/03/django-form-gotchas-dynamic-initial.html</guid><pubDate>Thu, 19 Mar 2015 13:22:00 GMT</pubDate></item><item><title>WD My Cloud NAS Setup On Linux</title><link>https://avilpage.com/2015/03/wd-my-cloud-nas-setup-on-ubuntu.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;I recently bought a WD My Cloud NAS&lt;sup id="fnref:nas"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2015/03/wd-my-cloud-nas-setup-on-ubuntu.html#fn:nas"&gt;1&lt;/a&gt;&lt;/sup&gt; device to store my personal data. I wanted to set it up on my Ubuntu machine. For WD My Cloud, there is no official support for Ubuntu or any other Linux distros. But setting up it is quite easy.&lt;/p&gt;
&lt;h4&gt;NAS Setup&lt;/h4&gt;
&lt;p&gt;Make sure You have connected power adapter &amp;amp; LAN cables to it. If You open Your router config, You will see WD My cloud in client list. Make note of its IP address. If You want, You can assign a static IP also in the router settings.&lt;/p&gt;
&lt;p&gt;Next step is to install NFS client package. NFS(Network File System) allows a system to share directories and files with others over a network. By using NFS, users and programs can access files on remote systems almost as if they were local files. So, update your packages &amp;amp; install &lt;code&gt;nfs-common&lt;/code&gt; package.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;update
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nfs-common
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can list folders which are available to mount using &lt;code&gt;showmount&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;showmount&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;ip-address&amp;gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create an empty folder to mount any of the folder you wanted and mount it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;rw,soft,intr,nfsvers&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;ip&amp;gt;:&amp;lt;folder-to-mount&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;path-to-mount&amp;gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now You can start moving data into/out of WD My Cloud.&lt;/p&gt;
&lt;p&gt;If You want to mount it automatically on boot, add following line to &lt;code&gt;/etc/fstab&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&amp;lt;ip&amp;gt;:&amp;lt;folder-to-mount&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;path-to-mount&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;nfs&lt;span class="w"&gt; &lt;/span&gt;rw,soft,intr,nfsvers&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Even though there is no official support for Ubuntu, WD My Cloud works pretty well with Ubuntu and other Linux distros. &lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:nas"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Network-attached_storage"&gt;https://en.wikipedia.org/wiki/Network-attached_storage&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2015/03/wd-my-cloud-nas-setup-on-ubuntu.html#fnref:nas" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>command-line</category><category>linux</category><category>ubuntu</category><guid>https://avilpage.com/2015/03/wd-my-cloud-nas-setup-on-ubuntu.html</guid><pubDate>Tue, 17 Mar 2015 08:50:00 GMT</pubDate></item><item><title>Install Oh-My-Zsh On Ubuntu!</title><link>https://avilpage.com/2015/03/install-oh-my-zsh-on-ubuntu.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;span style="line-height: 25.6000003814697px;"&gt;I crashed my  OS &amp;amp; I had to re install  all  things again. This  is  just  to  keep a track on how  to install zsh.&lt;/span&gt;&lt;br&gt;&lt;span style="line-height: 25.6000003814697px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="line-height: 25.6000003814697px;"&gt;For oh-my-zsh to work, You need to install zsh &amp;amp; git core first. To do that&lt;/span&gt;&lt;/div&gt;&lt;div class="highlight highlight-bash" style="background: rgb(255, 255, 255); box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;apt-get install zsh&lt;br&gt;apt-get install git-core&lt;/pre&gt;&lt;/div&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Now, You can install it by&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;&lt;span style="color: #333333; font-family: Consolas, Liberation Mono, Menlo, Courier, monospace;"&gt;&lt;span style="font-size: 13.6000003814697px; line-height: 19.7199993133545px;"&gt;curl -L http://install.ohmyz.sh | sh&lt;/span&gt;&lt;span style="font-size: 13.6000003814697px; line-height: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;Next, cha&lt;span style="line-height: 25.6000003814697px;"&gt;nge your shell to zsh&lt;/span&gt;&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;chsh -s `which zsh`&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6000003814697px; margin-bottom: 16px;"&gt;and then restart your system.&lt;/div&gt;&lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"&gt;&lt;code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"&gt;sudo shutdown -r 0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><category>command-line</category><category>linux</category><category>ubuntu</category><guid>https://avilpage.com/2015/03/install-oh-my-zsh-on-ubuntu.html</guid><pubDate>Sun, 15 Mar 2015 12:24:00 GMT</pubDate></item><item><title>Random Life Quotes #1</title><link>https://avilpage.com/2015/03/random-life-quotes-1.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-4RXqXCW5zmA/VQMW-R6nLAI/AAAAAAAANrw/_h_Yf8vMtLk/s1600/life-amazing-quotes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-4RXqXCW5zmA/VQMW-R6nLAI/AAAAAAAANrw/_h_Yf8vMtLk/s1600/life-amazing-quotes.jpg" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-jRtzw8ym6LY/VQMXCSWDF3I/AAAAAAAANsk/WJXk5V_eHEE/s1600/life-quotes4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="112" src="http://2.bp.blogspot.com/-jRtzw8ym6LY/VQMXCSWDF3I/AAAAAAAANsk/WJXk5V_eHEE/s1600/life-quotes4.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-U9iM8v2vhOE/VQMXAqENhmI/AAAAAAAANsQ/7yiNOe0tQMc/s1600/life-quotes21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-U9iM8v2vhOE/VQMXAqENhmI/AAAAAAAANsQ/7yiNOe0tQMc/s1600/life-quotes21.png" width="608"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-prz3TbB1P2M/VQMXBGd9jsI/AAAAAAAANsY/fgPAD-CkNJM/s1600/life-quotes22.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-prz3TbB1P2M/VQMXBGd9jsI/AAAAAAAANsY/fgPAD-CkNJM/s1600/life-quotes22.gif" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-g86Naeu-cvE/VQMXB09ooQI/AAAAAAAANsg/E82ZBtc5ctI/s1600/life-quotes22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-g86Naeu-cvE/VQMXB09ooQI/AAAAAAAANsg/E82ZBtc5ctI/s1600/life-quotes22.png" width="614"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-hbuAibhQ5RY/VQMW-VCqjYI/AAAAAAAANsI/Q0ORY40bQMY/s1600/life-quotes-amazing222.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="334" src="http://1.bp.blogspot.com/-hbuAibhQ5RY/VQMW-VCqjYI/AAAAAAAANsI/Q0ORY40bQMY/s1600/life-quotes-amazing222.jpg" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-cyKJmXYz7uM/VQMW-dq4zfI/AAAAAAAANr0/BogGn1mql0I/s1600/life-quotes-amazing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/-cyKJmXYz7uM/VQMW-dq4zfI/AAAAAAAANr0/BogGn1mql0I/s1600/life-quotes-amazing.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-jy2G7JYL4wM/VQMW_QNFxsI/AAAAAAAANr8/FV0JsalO5pI/s1600/life-quotes-best.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="622" src="http://1.bp.blogspot.com/-jy2G7JYL4wM/VQMW_QNFxsI/AAAAAAAANr8/FV0JsalO5pI/s1600/life-quotes-best.png" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-V_FOxFQeawk/VQMW_nAt1TI/AAAAAAAANsA/U0aI4TKHb1k/s1600/life-quotes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/-V_FOxFQeawk/VQMW_nAt1TI/AAAAAAAANsA/U0aI4TKHb1k/s1600/life-quotes.jpg" width="640"&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br&gt;
&lt;/div&gt;</description><category>quotes</category><guid>https://avilpage.com/2015/03/random-life-quotes-1.html</guid><pubDate>Fri, 13 Mar 2015 11:30:00 GMT</pubDate></item><item><title>How To Make Better Use Of Any Emacs Package?</title><link>https://avilpage.com/2015/03/how-to-make-better-use-of-any-emacs.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div id="preview" preview=""&gt;
      &lt;a href="https://github.com/jorgenschaefer/elpy" target="_blank"&gt;Elpy&lt;/a&gt; is an Emacs package that brings powerful Python editing to Emacs. While going
      through elpy issues, I came across an interesting thread, where someone asked this&lt;br&gt;
      &lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://4.bp.blogspot.com/-urQHNeVridQ/VPs1WMpjxTI/AAAAAAAANqc/QKVwPB_6ot0/s1600/elpy-emacs.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-urQHNeVridQ/VPs1WMpjxTI/AAAAAAAANqc/QKVwPB_6ot0/s1600/elpy-emacs.png" height="336" width="640"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div style="text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;This lead to this post. This post gives a brief introduction on getting familiar with any Emacs package &amp;amp; start hacking it quickly.&lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;

      &lt;h3 id="getting-started-"&gt;Getting Started:&lt;/h3&gt;
      Most Emacs packages provide a Readme file &amp;amp; some of them have good documentation too. Also there is
      emacswiki where some other hacks will be available.&lt;br&gt;
      &lt;br&gt;
      That will be help You to get started with any package. You can start using default functions/key bindings.&lt;br&gt;
      &lt;br&gt;
      If we take elpy as a case study, it has &lt;a href="https://github.com/jorgenschaefer/elpy/blob/master/README.rst" target="_blank"&gt;Readme file&lt;/a&gt; which
      shows how to install elpy. It also has a &lt;a href="http://elpy.readthedocs.org/en/latest/index.html" target="_blank"&gt;good documentation&lt;/a&gt; about elpy
      &amp;amp; some of its important features.&lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;

      &lt;h3 id="getting-under-the-hood-"&gt;Getting Under The Hood:&lt;/h3&gt;

      Now lets see some interesting stuff which Emacs packages are capable of but read me file or
      documentation wont contain.&lt;br&gt;
      &lt;br&gt;
      One useful package I recommend for this purpose is &lt;a href="https://github.com/emacs-helm/helm-descbinds" target="_blank"&gt;helm-descbindings&lt;/a&gt; which
      shows key bindings of all available modes. You can also filter among them.&lt;br&gt;
      &lt;br&gt;
      Here You will come to know about few useful functions an Emacs package is capable of doing.&lt;br&gt;
      &lt;br&gt;
      In the case of elpy, You can see something like this.&lt;br&gt;
      &lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://3.bp.blogspot.com/-k0GV9-BtdmQ/VPs3oFuqdEI/AAAAAAAANqo/sEu3kFCeDFU/s1600/elpy-emacs2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-k0GV9-BtdmQ/VPs3oFuqdEI/AAAAAAAANqo/sEu3kFCeDFU/s1600/elpy-emacs2.png" height="516" width="640"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div style="text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;&lt;br&gt;
      But You cannot find all key bindings here as some of them might be shadowed (or taken away) by other packages.&lt;br&gt;
      &lt;br&gt;
      To specify a key binding, Emacs packages use a define-key function. So if You open source code of the package and search for define-key, you will see all
      key bindings there.&lt;br&gt;
      &lt;br&gt;
      If you search for define-key in elpy.el You will come across this&lt;br&gt;
      &lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://3.bp.blogspot.com/-kbACCkJmxIg/VPs6x97q2XI/AAAAAAAANq0/1Aa_TIcbjU0/s1600/elpy-emacs21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-kbACCkJmxIg/VPs6x97q2XI/AAAAAAAANq0/1Aa_TIcbjU0/s1600/elpy-emacs21.png" height="640" width="632"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div style="text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;Now You know a few functions &amp;amp; their key bindings which are not present in the documentation.&lt;br&gt;
      &lt;br&gt;
      If there are any key bindings that are not useful You can unbind them.&lt;br&gt;
      For example elpy has "C-c C-p" binded to (elpy-flymake-previous-error) which I won't use much. So I can unbind it&lt;br&gt;
      &lt;br&gt;
      &lt;pre&gt;
&lt;code&gt;    (&lt;span class="hljs-keyword"&gt;define-key&lt;/span&gt; elpy-mode-map &lt;span class="hljs-list"&gt;(&lt;span class="hljs-keyword"&gt;kbd&lt;/span&gt; &lt;span class="hljs-string"&gt;"C-c C-p"&lt;/span&gt;)&lt;/span&gt; &lt;span class="hljs-literal"&gt;nil&lt;/span&gt;)&lt;/code&gt;
&lt;/pre&gt;

This sets "C-c C-p" to nil.

&lt;h3 id="digging-deeper-"&gt;Digging Deeper:&lt;/h3&gt;

So far we have seen what an Emacs package is capable of doing. Now, lets start tweaking it a little bit.&lt;br&gt;
      &lt;br&gt;
      The first thing You can do is start using interactive functions right away. Functions in Emacs package which has interactive form are callable commands.
      You can invoke them using M-x and function name. You will find a lot of them here.&lt;br&gt;
      &lt;br&gt;
      If you want to find all interactive commands in an emacs package, You have to search through source code &amp;amp; find them. Instead if you have &lt;a href="https://github.com/emacs-helm/helm" target="_blank"&gt;helm&lt;/a&gt; (If You are not using Helm, I highly recommend You to start using it.) installed, if you
      type M-x &amp;amp; few letters of the package name, it will narrow down all the interactive functions of that package.&lt;br&gt;

      &lt;div style="text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        Elpy has a lot of interactive commands, You can see a few of them here.
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://3.bp.blogspot.com/-QomW6hrTdnw/VPs8T7ifL1I/AAAAAAAANrA/XjSc8-zJRDI/s1600/elpy-emacs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-QomW6hrTdnw/VPs8T7ifL1I/AAAAAAAANrA/XjSc8-zJRDI/s1600/elpy-emacs.png" height="640" width="376"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div style="text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;&lt;br&gt;
      Now You can start bindings keys to any of the functions that You like. Previously We have unbinded a key. Now lets bind it to some function.&lt;br&gt;
      &lt;br&gt;
          (global-set-key (kbd "C-c C-p") 'elpy-set-project-root)&lt;br&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;&lt;br&gt;

      &lt;h3 id="digging-deeper-"&gt;Getting (in)sane With Lisp:&lt;/h3&gt;

      &lt;div&gt;
        So far we have just used Emacs package as it is. If You know a bit of lisp, You can start tweaking existing functions or You can write Your own
        functions. This mostly depends on how You want to use &amp;amp; customize a package. You can do a lot of fun stuff. Enjoy lisping :)
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;
     &lt;/div&gt;
  &lt;/div&gt;</description><category>emacs</category><guid>https://avilpage.com/2015/03/how-to-make-better-use-of-any-emacs.html</guid><pubDate>Sat, 07 Mar 2015 12:53:00 GMT</pubDate></item><item><title>BangPypers Talks - Emacs  As Python IDE!</title><link>https://avilpage.com/2015/02/bangpypers-talks-emacs-as-python-ide.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;a href="http://bangalore.python.org.in/" target="_blank"&gt;BangPypers&lt;/a&gt; is the Bangalore Python Usergroup. It is one of the largest and oldest Python user groups in India. On 3rd Saturday of every month there will be meetup. This month(Feb 2014) took place at IBM, Domlur. I gave a talk about setting up Emacs as Python IDE.&lt;br&gt;&lt;br&gt;When  I started using Emacs, I spent a lot of time to configure &amp;amp; make it an IDE. Recently I came across &lt;a href="https://github.com/jorgenschaefer/elpy" target="_blank"&gt;elpy&lt;/a&gt;(emacs lisp python enviroment) &amp;amp;  liked it a lot. With just couple of lines You can turn emacs into Python IDE. So I stressed a lot about elpy during the talk.&lt;br&gt;&lt;br&gt;I talked about other important packages I used &amp;amp; other things that can be done with emacs.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://bangalore.python.org.in/blog/2015/02/21/feb-meetup-report/"&gt;Meetup Report&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://chillaranand.github.io/emacs-py-ide/" target="_blank"&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="https://github.com/ChillarAnand/.emacs.d" target="_blank"&gt;My .emacs.d&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;</description><category>bangalore</category><category>emacs</category><category>python</category><guid>https://avilpage.com/2015/02/bangpypers-talks-emacs-as-python-ide.html</guid><pubDate>Mon, 23 Feb 2015 15:02:00 GMT</pubDate></item><item><title>Bangalore Django User Group - Beginners Workshop</title><link>https://avilpage.com/2015/02/bangalore-django-user-group-beginners.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;During &lt;a href="http://www.avilpage.com/2014/12/bangpypers-dev-sprint.html" target=""&gt;BangPypers december dev sprint&lt;/a&gt; Few weeks back, Krace &amp;amp; Siva asked me if I can take a Django workshop. I agreed. They have worked on logistics &amp;amp; scheduled for February at IBM, Domlur.&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;I reached there by 9.30 AM. 26 people attended the session. Due to some problems we started a bit late than what we have planned. Krace, Siva &amp;amp; Ankur assisted a lot during the session.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;We planned to cover the basics of Django &amp;amp; CRUD operations by building a simple app. We covered basics &amp;amp; simple create view. Due to time constraint we were unable to cover the remaining.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Content: &lt;a href="https://github.com/ChillarAnand/django-bookmarks"&gt;https://github.com/ChillarAnand/django-bookmarks&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Slides: &lt;a href="http://chillaranand.github.io/django-bookmarks/"&gt;http://chillaranand.github.io/django-bookmarks/&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;</description><category>bangalore</category><category>django</category><category>python</category><guid>https://avilpage.com/2015/02/bangalore-django-user-group-beginners.html</guid><pubDate>Mon, 16 Feb 2015 15:10:00 GMT</pubDate></item><item><title>14 Great Quotes About Python Programming Language</title><link>https://avilpage.com/2014/12/14-great-quotes-about-python.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;A collection of quotes about Python programming language!&lt;br&gt;&lt;br&gt;
    &lt;div&gt;
        &lt;div style="background: #ececec; padding: 18px;"&gt;The joy of coding Python should be in seeing short, concise,
            readable classes that express a lot of action in a small amount of clear code -- not in reams of trivial
            code that bores the reader to death.&lt;br&gt;&lt;br&gt;- Guido van Rossum
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div&gt;
        &lt;div style="background: #ececec; padding: 18px;"&gt;My favorite language for maintainability is Python. It has
            simple, clean syntax, object encapsulation, good library support, and optional named parameters.&lt;br&gt;&lt;br&gt;-
            Bram Cohen
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div&gt;&lt;br&gt;&lt;br&gt;
        &lt;div style="background: #ececec; padding: 18px;"&gt;As it seems to me, in Perl you have to be an expert to
            correctly make a nested data structure like, say, a list of hashes of instances. In Python, you have to be
            an idiot not to be able to do it, because you just write it down.&lt;br&gt;&lt;br&gt;- Peter Norvig
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: #ececec; padding: 18px;"&gt;In many ways, it's a dull language, borrowing solid old concepts
        from many other languages &amp;amp; styles: boring syntax, unsurprising semantics, few automatic coercions, etc etc.
        But that's one of the things I like about Python. &lt;br&gt;&lt;br&gt;- Tim Peters
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: #ececec; padding: 18px;"&gt;Everyone knows that any scripting language shootout that doesn't
        show Python as the best language is faulty by design. &lt;br&gt;&lt;br&gt;- Max M
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: #ececec; padding: 18px;"&gt;Every sufficiently advanced LISP application will eventually
        reimplement Python.&lt;br&gt;&lt;br&gt;- Hodgson's Law
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: #ececec; padding: 18px;"&gt;The  canonical, "Python is a great first language", elicited,
        "Python is a great last language!"&lt;br&gt;&lt;br&gt;- Noah Spurrier
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: #ececec; padding: 18px;"&gt;Python is the "most powerful language you can still read".&lt;br&gt;&lt;br&gt;-
        Paul Dubois
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: #ececec; padding: 18px;"&gt;"Python tricks" is a tough one, cuz the language is so clean. E.g.,
        C makes an art of confusing pointers with arrays and strings, which leads to lotsa neat pointer tricks; APL
        mistakes everything for an array, leading to neat one-liners; and Perl confuses everything period, making each
        line a joyous adventure ;-)&lt;br&gt;&lt;br&gt; - Tim Peters
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: rgb(236, 236, 236); padding: 18px;"&gt;&lt;span style="background-color: transparent;"&gt;Python is a truly wonderful language. When somebody comes up with a good idea it takes about 1 minute and five lines to program something that almost does what you want. Then it takes only an hour to extend the script to 300 lines, after which it still does almost what you want.&lt;/span&gt;&lt;br&gt;&lt;span style="background-color: transparent;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="background-color: transparent;"&gt;- Jack Jansen&lt;/span&gt;&lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: rgb(236, 236, 236); padding: 18px;"&gt;&lt;span style="background-color: transparent;"&gt;Python is an experiment in how much freedom programmers need. Too much freedom and nobody can read another's code; too little and expressiveness is endangered.&lt;/span&gt;&lt;br&gt;&lt;span style="background-color: transparent;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="background-color: transparent;"&gt;- Guido van Rossum&lt;/span&gt;
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: rgb(236, 236, 236); padding: 18px;"&gt;I suggested holding a "Python Object Oriented
        Programming Seminar", but the acronym was unpopular.&lt;br&gt;&lt;br&gt;- Joseph Strout
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: rgb(236, 236, 236); padding: 18px;"&gt;PYTHON = (P)rogrammers (Y)earning (T)o (H)omestead (O)ur
        (N)oosphere.&lt;br&gt;&lt;br&gt;- Sean McGrath
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: rgb(236, 236, 236); padding: 18px;"&gt;Abstraction is one of those notions that Python tosses
        out the window, yet expresses very well.&lt;br&gt;&lt;br&gt;- Gordon McMillan,
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;div style="background: rgb(236, 236, 236); padding: 18px;"&gt;&lt;span style="background-color: transparent;"&gt;Surprisingly enough, Python has taught me more about Lisp than Lisp ever did ;-).&lt;/span&gt;&lt;br&gt;&lt;span style="background-color: transparent;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="background-color: transparent;"&gt;- Glyph Lefkowitz&lt;/span&gt;
    &lt;/div&gt;
    &lt;br&gt;&lt;br&gt;Sources:&lt;br&gt;&lt;a href="https://web.archive.org/web/20000815231951/http://starship.python.net/crew/amk/quotations/python-quotes.html" target="_blank"&gt;Starship Python&lt;/a&gt;&lt;br&gt;&lt;a href="http://stgray.com/quotes/pythonquotes.html" target="_blank"&gt;Scott's
        space&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>python</category><category>quotes</category><guid>https://avilpage.com/2014/12/14-great-quotes-about-python.html</guid><pubDate>Tue, 30 Dec 2014 08:11:00 GMT</pubDate></item><item><title>Importing &amp; Exporting JSON Data To mongoDB!</title><link>https://avilpage.com/2014/12/importing-exporting-json-data-to-mongodb.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;code&gt;mongoimport&lt;/code&gt; imports JSON, CSV or TSV data to mongoDB. If You are importing JSON data from a file to db, the file should have only one document per line and there shouldn't be any delimiters at the end of file. If You have a file &lt;code&gt;sample.json&lt;/code&gt; like this&lt;br&gt;&lt;pre&gt;{"num":1,"status":"ok"}&lt;br&gt;{"num":2,"status":"ok"}&lt;br&gt;{"num":3,"status":"ok"}&lt;br&gt;{"num":4,"status":"ok"}&lt;/pre&gt;You can directly import it into db using&lt;br&gt;&lt;pre&gt;mongoimport --db &amp;lt;db&amp;gt; --collections &amp;lt;collection&amp;gt; --file sample.json&lt;/pre&gt;This is straight forward and works well. But some third party services provide data in the form of JSON array like this&lt;br&gt;&lt;pre&gt;[&lt;br&gt;    {"num":1,"status":"ok"},&lt;br&gt;    {"num":2,"status":"ok"},&lt;br&gt;    {"num":3,"status":"ok"},&lt;br&gt;    {"num":4,"status":"ok"},&lt;br&gt;]&lt;br&gt;&lt;/pre&gt;If You try to import it, it throws FailedToParse error. For this, You need to pass additional param jsonArray.&lt;br&gt;&lt;pre&gt;mongoimport --db &amp;lt;db&amp;gt; --collections &amp;lt;collection&amp;gt; --file sample.json --jsonArray&lt;/pre&gt;If You want to export Your collection as a json dump, You can use mongoexport command&lt;br&gt;&lt;pre&gt;mongoexport --db &amp;lt;db&amp;gt; --collections &amp;lt;collection&amp;gt; --out sample.json&lt;/pre&gt;This exports data into JSON format with one document in a row.&lt;br&gt;&lt;br&gt;If You pass jsonArray as an optional parameter, it will export the collection as a jsonArray&lt;br&gt;&lt;pre&gt;mongoexport --db &amp;lt;db&amp;gt; --collections &amp;lt;collection&amp;gt; --out sample.json --jsonArray&lt;/pre&gt;If You are lazy to type, You can use  &lt;br&gt;&lt;pre&gt;mongoexport --d &amp;lt;db&amp;gt; --c &amp;lt;collection&amp;gt; --o sample.json --jsonArray&lt;/pre&gt;&lt;br&gt;References:: mongoDB docs - &lt;a href="http://docs.mongodb.org/manual/reference/program/mongoimport/" target="_blank"&gt;mongoimport&lt;/a&gt;, &lt;a href="http://docs.mongodb.org/manual/reference/program/mongoexport/#bin.mongoexport" target="_blank"&gt;mongoexport&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;style&gt;code {  font-size: 1em; font-family: 'Menlo',Courier,monotype; padding: 2px 4px; color: #373737; background-color: #f7f7f9; border: 1px solid #e1e1e8; overflow: hidden; }  pre { border-bottom-left-radius: 3px;  border-bottom-right-radius: 3px;  border-top-left-radius: 3px;  border-top-right-radius: 3px;  border: 1px solid rgb(170, 204, 153);  font-family: monospace, sans-serif;  font-size: 15px;  line-height: 18.5279998779297px;  overflow-x: auto; overflow-y: hidden;  padding: 5px; }  } &lt;/style&gt;&lt;/div&gt;</description><category>database</category><guid>https://avilpage.com/2014/12/importing-exporting-json-data-to-mongodb.html</guid><pubDate>Sun, 28 Dec 2014 08:03:00 GMT</pubDate></item><item><title>7 Easter Eggs Hiding In Your Emacs!</title><link>https://avilpage.com/2014/12/7-easter-eggs-hiding-in-your-emacs.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I just came across this xkcd comic about Real programmers.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/-wLJ6QY0kggY/VJ8RmRpdEvI/AAAAAAAANgc/DlofBpY-6Wo/s1600/real_programmers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-wLJ6QY0kggY/VJ8RmRpdEvI/AAAAAAAANgc/DlofBpY-6Wo/s1600/real_programmers.png" height="348" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;I started emacs invoked butterfly command and that's my first easter egg. Later I digged around and found several games &amp;amp; a few other easter eggs. Here are a few of them.&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;M-x butterfly: Flip the desired bit on the drive platter.&lt;br&gt;&lt;br&gt;M-x doctor: Switch to *doctor* buffer and start giving psychotherapy.&lt;br&gt;&lt;br&gt;M-x zone: zone out completely.&lt;br&gt;&lt;br&gt;M-x life: runs Conway's "Life" cellular automaton.&lt;br&gt;&lt;br&gt;M-x studlify-buffer: stUdlIfY-RegioN stUdlIfY-CaSeS thE region.&lt;br&gt;&lt;br&gt;M-x landmark: Start or resume an Landmark game.&lt;br&gt;&lt;br&gt;M-x animate-birthday-present: Return a birthday present.&lt;br&gt;&lt;br&gt;M-x yow: Return or display a random Zippy quotation.&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;Notes:&lt;br&gt;1. yow was removed in Emacs 22 due to copyright problems. But you can get it manually.&lt;br&gt;&lt;br&gt;   Download quotes file to your .emacs.d directory&lt;br&gt;   M-! wget bit.ly/emacs-yow -O ~/.emacs.d/yow.txt.gz&lt;br&gt;&lt;br&gt;   Specify the path of file in Your init file&lt;br&gt;   (setq yow-file "~/.emacs.d/yow.txt.gz")&lt;br&gt;&lt;br&gt;2. To know about each of the easter eggs, you can use help&lt;br&gt;   C-h f RET &amp;lt;function&amp;gt; RET&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://www.avilpage.com/search/label/emacs"&gt;More articles about Emacs&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>emacs</category><guid>https://avilpage.com/2014/12/7-easter-eggs-hiding-in-your-emacs.html</guid><pubDate>Sat, 27 Dec 2014 14:59:00 GMT</pubDate></item><item><title>BangPypers - Python Dev Sprint</title><link>https://avilpage.com/2014/12/bangpypers-dev-sprint.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Here is the definition of &lt;a href="http://en.wikipedia.org/wiki/Sprint_(software_development)" target="_blank"&gt;sprint from Wikipedia&lt;/a&gt;:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-BLq7LzyL2zk/VJgS391dgyI/AAAAAAAANfM/9XFQ2TIQJHY/s1600/bangpypers-sprint2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-BLq7LzyL2zk/VJgS391dgyI/AAAAAAAANfM/9XFQ2TIQJHY/s1600/bangpypers-sprint2.png" height="88" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;On 3rd Saturday of every month there will be a meetup for &lt;a href="http://www.meetup.com/BangPypers/" target="_blank"&gt;Python developers in Bangalore&lt;/a&gt;(BangPypers) to have talks and workshops. This month instead of talks/workshops, a dev sprint was held. The basic idea was to encourage Python developers to contribute to any open source projects or work on their open source projects.&lt;div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;I was working on Nidaba, a project to extract information from StackOverflow dumps. I went to the meetup and gave a brief description about it. Several people were interested to work. I helped them a bit on getting started and the issues to solve. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;By the end of event, I got one pull request which fixed a typo in setup file. Few people helped in adding couple of utility functions for the project. A couple of them were interested to continue working on with it in the coming weekends. In the end PSSI sponsored T-shirt :) &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Here are a few snapshots of event.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-5MxNXfwVqbo/VJgZhMXYInI/AAAAAAAANfg/itJLP-R4NYA/s1600/bangpypers-meetup22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-5MxNXfwVqbo/VJgZhMXYInI/AAAAAAAANfg/itJLP-R4NYA/s1600/bangpypers-meetup22.png" height="425" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-_d98prRclZM/VJgZg7bN_sI/AAAAAAAANfc/Hnsz1pBPIhk/s1600/bangpypers-meetup.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-_d98prRclZM/VJgZg7bN_sI/AAAAAAAANfc/Hnsz1pBPIhk/s1600/bangpypers-meetup.JPG" height="424" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-oU-4mZ_Kaw8/VJgZhLuWhRI/AAAAAAAANfo/iyEzB3o-Eyo/s1600/bangpypers-sprint3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-oU-4mZ_Kaw8/VJgZhLuWhRI/AAAAAAAANfo/iyEzB3o-Eyo/s1600/bangpypers-sprint3.png" height="426" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>bangalore</category><category>python</category><guid>https://avilpage.com/2014/12/bangpypers-dev-sprint.html</guid><pubDate>Mon, 22 Dec 2014 07:47:00 GMT</pubDate></item><item><title>ది పైథాన్ పారడాక్స్ (The Python Paradox)</title><link>https://avilpage.com/2014/12/python-paradox.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;ఆగస్టు 2004 లో ఈ వ్యాసం &lt;a href="http://paulgraham.com/pypar.html" target="_blank"&gt;పాల్ గ్రాహం&lt;/a&gt;  ఆంగ్లం లో వ్రాసారు. ఇది తెలుగు అనువాదం.&lt;br&gt;&lt;br&gt;"మీరు ఒక Java ప్రాజెక్ట్  కన్నా Python ప్రాజెక్ట్ మీద పని చేయడానికి తెలివైన  ప్రోగ్రామర్లను  పొందవచ్చు" అని నేను &lt;a href="http://paulgraham.com/gh.html" target="_blank"&gt;ఇటీవల చర్చ &lt;/a&gt;లో అన్న మాటలకు ప్రజలు చాలా  అప్సెట్ అయ్యారు.&lt;br&gt;&lt;br&gt;దానికి అర్థం  Java  ప్రోగ్రామర్లు మొద్దు అని కాదు. Python ప్రోగ్రామర్లు స్మార్ట్ గా  ఉంటారు అని. ఒక కొత్త ప్రోగ్రామింగ్ భాష నేర్చుకోవడం కష్టమైన పని. ప్రజలు ఒక ఉద్యోగం పొందటానికి Python నేర్చుకోరు. వారు పైథాన్ ఎందుకు నేర్చుకుంటారంటే వారికి స్వచ్ఛంగా ప్రోగ్రామ్మింగ్ అంటే  ఇష్టం మరియు వారికి ఇప్పటికే తెలిసిన భాషలు సంతృప్తి ఇవ్వకపోవడం వలన. అందువల్లే  కంపెనీలు Python ప్రోగ్రామర్లను నియమించుకుంటాయి. ఈ concept కి ఒక మంచి పేరు ఏది తట్టలేదు, అందుకే నేను దీన్నిPython పారడాక్స్ అని పిలుస్తాను.  ఒక సంస్థ software వ్రాయడానికి తులనాత్మకంగా esoteric భాషను  ఎంచుకుంటే, వారు మంచి ప్రోగ్రామర్లను  నియమించుకుంటారు. ఎందుకంటే అలాంటి బాష నేర్చుకోవాలని చాలా కొద్ది మందే కుతూహలంగా ఉంటారు. ప్రోగ్రామర్లకి ఈ పారడాక్స్ మరింత వర్తిస్తుంది. మీరు ఒక మంచి ఉద్యోగం పొందడానికి నేర్చుకునే భాష, ప్రజలు కేవలం ఉద్యోగం పొందడానికి  మాత్రమే నేర్చుకోలేదు.&lt;br&gt;&lt;br&gt;కేవలం కొన్ని తెలివైన కంపెనీలు మాత్రమె ఇప్పటివరకు ఈ విషయాన్ని గ్రహించాయి. కానీ ఇక్కడ ఇంకో రకమైన ఎంపిక జరగుతోంది. సరిగ్గా  అటువంటి కంపెనీలలోనే  ప్రోగ్రామర్లు పని చేయాలనీ కోరుకుంటున్నారు. ఉదాహరణకు, గూగుల్ Java ప్రోగ్రామింగ్ ఉద్యోగాలు ప్రకటన ఇచ్చినప్పుడు, వారు Python అనుభవం తప్పనిసరిగా అడుగుతున్నారు.&lt;br&gt;&lt;br&gt;అన్ని భాషలు విస్తృతంగా ఉపయోగించిన  నా  స్నేహితుడు, దాదాపు అన్ని ప్రాజెక్ట్ ల  కొరకు Python ఉపయోగిస్తాడు. అందుకు ప్రధాన కారణం source code చదవటానికి చాల అనువుగా ఉండటం. ఆ ఒక్క కారణానికి మరొక భాషను ఎంచుకోవడం ఒక అల్పమైన కారణం అని మీరు అనుకోవచ్చు. కాని అది అనుకున్నంత అల్పమైన కారణం కాదు. ఎందుకంటే source code ను రాయడం కంటే చదవడం లో ఎక్కువ సమయం వెచ్చిస్తారు. ఒక శిల్పి మట్టి ముద్దల్ని పేర్చుకు పోయినట్లు మీరు కూడా source code blobs ని పేర్చుకుంటూపోతారు. అస్తవ్యస్తంగా పేర్చిన మట్టి ముద్దలు శిల్పిని  చికాకుపరిచినట్లే, చదవటానికి అనువుగా లేని ఒక భాష, ప్రోగ్రామర్ ని చికాకు పరుస్తుంది.&lt;br&gt;&lt;br&gt;Source code అవలక్షణం ప్రస్తావన వద్ద, ప్రజలు Perl ను గుర్తు చేసుకుంటారు. కానీ నేను మాట్లాడేది Perl యొక్క ఉపరిభాగ సంబంధిత  అందం గురించి కాదు. నిజమైన  అవలక్షణం కఠినంగ కనిపించే వాక్యనిర్మాణం కాదు, కానీ తప్పు patterns ని అనుసరించి ప్రోగ్రమ్స్  వ్రాయటం. Perl ఒక కార్టూన్ పాత్ర తిట్లు వల్లే  ఉండవచ్చు, కానీ కొన్ని చోట్ల అది Python ను అధిగమించిన &lt;a href="http://paulgraham.com/icad.html" target="_blank"&gt;సందర్భాలు&lt;/a&gt; ఉన్నాయి.&lt;br&gt;&lt;br&gt;ఇప్పటివరకు, ఏమైనప్పటికీ. రెండు భాషలు &lt;a href="http://paulgraham.com/hundred.html" target="_blank"&gt;కదిలే లక్ష్యాలు &lt;/a&gt;.  కానీ ఈ రెండు భాషలు కుడా Ruby, (Icon, Joy, J , Lisp &amp;amp; Small Talk) మాదిరి,  నిజంగా ప్రోగ్రామింగ్ పట్టించుకుని,  ఉపయోగించే   ప్రజలచే రూపొందించబడినవి అన్న సత్యాన్ని గుర్తిస్తున్నాయి.&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>python</category><category>telugu</category><guid>https://avilpage.com/2014/12/python-paradox.html</guid><pubDate>Fri, 19 Dec 2014 10:21:00 GMT</pubDate></item><item><title>Generate Sphinx Friendly Docstrings For Python Functions In Emacs!</title><link>https://avilpage.com/2014/12/generate-sphinx-friendly-docstrings-for.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Today, I went to &lt;a href="http://www.meetup.com/Bangalore-Django-User-Group/events/219082263/" target="_blank"&gt;Django REST Framework Workshop&lt;/a&gt;. After the workshop is completed,  and we were discussing about Emacs, &lt;a href="http://www.kracekumar.com/" target="_blank"&gt;Krace&lt;/a&gt; showed this cool plugin &lt;a href="https://github.com/naiquevin/sphinx-doc.el" target="_blank"&gt;sphinx-doc&lt;/a&gt;, it inserts docstring skeleton for Python functions/methods as per the requirement of the Sphinx documentation generator.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-FHLnsul5mEg/VIxxkDO3ttI/AAAAAAAANeI/Q8xYC9S-MMg/s1600/emacs-python-sphinx.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-FHLnsul5mEg/VIxxkDO3ttI/AAAAAAAANeI/Q8xYC9S-MMg/s1600/emacs-python-sphinx.gif" height="560" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;Installation:&lt;/h3&gt;To install it from MELPA, run &lt;i&gt;"M-x package-list-packages"&lt;/i&gt;, search for &lt;i&gt;"sphinx-doc" , m&lt;/i&gt;ark it with i and press x to install.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;Configuration:&lt;/h3&gt;Add these lines to Your emacs config to enable sphinx-doc-mode.&lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;(add-hook 'python-mode-hook (lambda ()&lt;br&gt;                  (require 'sphinx-doc)&lt;br&gt;                  (sphinx-doc-mode t)))&lt;/pre&gt;&lt;/div&gt;If you document your code(infact you should), this plugin saves quite a few strokes!  &lt;/div&gt;</description><category>emacs</category><category>python</category><guid>https://avilpage.com/2014/12/generate-sphinx-friendly-docstrings-for.html</guid><pubDate>Sat, 13 Dec 2014 11:59:00 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #2 - Check If App Is Production Ready</title><link>https://avilpage.com/2014/12/django-check-app-ready-production.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Before deploying Your Django app, You need to make sure security, logging and other issues are taken care. Django provides a simple &lt;a href="https://docs.djangoproject.com/en/dev/howto/deployment/checklist/" target="_blank"&gt;deployment checklist&lt;/a&gt; which helps a lot. In &lt;a href="https://docs.djangoproject.com/en/dev/ref/django-admin/#django-admin-option---deploy" target="_blank"&gt;development version&lt;/a&gt; Django provides &lt;i&gt;--deploy &lt;/i&gt;option, which does some security checks. You can run it with&lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;python manage.py check --deploy --settings=production_settings&lt;/pre&gt;&lt;div&gt;I have just created a new project and Django identified 6 security issues in it.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;→ python manage.py check --deploy                               &lt;br&gt;System check identified some issues:&lt;br&gt;WARNINGS:&lt;br&gt;?: (security.W001) You do not have 'django.middleware.security.SecurityMiddleware' in your MIDDLEWARE_CLASSES so the SECURE_HSTS_SECONDS, SECURE_CONTENT_TYPE_NOSNIFF, SECURE_BROWSER_XSS_FILTER, and SECURE_SSL_REDIRECT settings will have no effect.?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.&lt;br&gt;?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE_CLASSES, but you have not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.&lt;br&gt;?: (security.W017) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE_CLASSES, but you have not set CSRF_COOKIE_HTTPONLY to True. Using an HttpOnly CSRF cookie makes it more difficult for cross-site scripting attacks to steal the CSRF token.&lt;br&gt;?: (security.W018) You should not have DEBUG set to True in deployment.&lt;br&gt;?: (security.W019) You have 'django.middleware.clickjacking.XFrameOptionsMiddleware' in your MIDDLEWARE_CLASSES, but X_FRAME_OPTIONS is not set to 'DENY'. The default is 'SAMEORIGIN', but unless there is a good reason for your site to serve other parts of itself in a frame, you should change it to 'DENY'.&lt;br&gt;&lt;br&gt;System check identified 6 issues (0 silenced).&lt;/pre&gt;&lt;/div&gt;&lt;br&gt;However this doesn't identify issues like absence of 404.html, 500.html templates, email setup, admin emails,  presence of print, pdb statements. There is a Django package called &lt;a href="https://github.com/agiliq/django-production-ready" target="_blank"&gt;django-production-ready&lt;/a&gt; which checks for these issues.&lt;br&gt;&lt;br&gt;To the new project just created, I have added a new file, which has a print &amp;amp; pdb statements. I have installed django-production ready, added &lt;i&gt;prodready &lt;/i&gt; to installed apps and ran &lt;i&gt;is_it_ready &lt;/i&gt;management command which produced a neat log of all issues.&lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;→ python manage.py is_it_ready&lt;br&gt;--------------------&lt;br&gt;Production ready: No&lt;br&gt;--------------------&lt;br&gt;Possible errors:&lt;br&gt;    * Enter valid email address in ADMINS section&lt;br&gt;    * Enter valid email address in MANAGERS section&lt;br&gt;    * Template 404.html does not exist&lt;br&gt;    * Template 500.html does not exist&lt;br&gt;    * Setup E-mail host&lt;br&gt;    * Set a valid email for SERVER_EMAIL&lt;br&gt;    * Set a valid email for DEFAULT_FROM_EMAIL&lt;br&gt;    * You have one or more ipdb import  statements&lt;br&gt;    * You have one or more print statements&lt;br&gt;&lt;/pre&gt;&lt;div&gt;This comes in handy to quickly make sure a lot of issues are taken care and the app is ready for deployment!&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2014/12/django-check-app-ready-production.html</guid><pubDate>Fri, 12 Dec 2014 08:24:00 GMT</pubDate></item><item><title>Search, Play &amp; Download YouTube Videos From Command Line</title><link>https://avilpage.com/2014/12/tech-search-play-download-youtube.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;If You are using Linux,  You might be familiar with &lt;a href="http://rg3.github.io/youtube-dl/" target="_blank"&gt;youtube-dl&lt;/a&gt;, a small command-line program to download videos from &lt;a href="http://youtube.com/" target="_blank"&gt;YouTube&lt;/a&gt; and a few more sites. But You need to go to YouTube, grab the url and then give it to youtube-dl to download it.&lt;br&gt;&lt;br&gt;&lt;a href="https://github.com/np1/mps-youtube" target="_blank"&gt;mps-youtube&lt;/a&gt;, a terminal based YouTube player makes it possible to browse, play &amp;amp; download videos right from the terminal.&lt;br&gt;&lt;br&gt;You can install it using pip  &lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;pip install mps-youtube&lt;/pre&gt;&lt;/div&gt;and start using in with&lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;mpsyt&lt;/pre&gt;&lt;/div&gt;It is better to set an alias for this&lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;alias yt="mpsyt"&lt;/pre&gt;By default it is configured to search music category and stream audio only. You can change it&lt;br&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;set music_search false&lt;br&gt;set show_video true&lt;/pre&gt;To get help, just press h.&lt;br&gt;To search for videos about Katy Perry, type /katy perry.&lt;br&gt;To stream a song, enter the number of the song and enter.&lt;br&gt;To download a video, type d &amp;lt;number&amp;gt; and it shows all the available formats, then you can select any video of your choice and download it.&lt;br&gt;&lt;br&gt;Here are a few screenshots of it.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-FyTu5R7uNeU/VH3NT3NboDI/AAAAAAAANZA/ICRbFAvwLEs/s1600/terminal-youtube1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-FyTu5R7uNeU/VH3NT3NboDI/AAAAAAAANZA/ICRbFAvwLEs/s1600/terminal-youtube1.png" height="356" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-15RpL2mZyHk/VH3NUP6jEaI/AAAAAAAANZI/5RyepTegbAc/s1600/terminal-youtube2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-15RpL2mZyHk/VH3NUP6jEaI/AAAAAAAANZI/5RyepTegbAc/s1600/terminal-youtube2.png" height="358" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-z38bcLKsjRo/VH3NT4dUrRI/AAAAAAAANZE/doElqCxTG4k/s1600/terminal-youtube3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-z38bcLKsjRo/VH3NT4dUrRI/AAAAAAAANZE/doElqCxTG4k/s1600/terminal-youtube3.png" height="358" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>python</category><category>terminal</category><guid>https://avilpage.com/2014/12/tech-search-play-download-youtube.html</guid><pubDate>Tue, 02 Dec 2014 09:04:00 GMT</pubDate></item><item><title>Mirror A Website (Or Part Of Website) In Split Second!</title><link>https://avilpage.com/2014/11/mirror-website-quickly.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: left;"&gt;Occasionally it is necessary for developers to mirror a website. It is super easy to do this in no time.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;1. Getting A Copy Of Original Site:&lt;/h3&gt;&lt;div&gt;You can use the powerful tool wget for this. If you are familiar with *nix, you might have used it to fetch a single page or files to your system. But wget is capable of doing lot more than that. To download an entire site, you can use&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;wget --recursive --page-requisites --convert-links www.avilpage.com&lt;br&gt;# if you are lazy to type use &lt;br&gt;# wget -rpk www.avilpage.com&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;This downloads all components(sounds, images etc)  of www.avilpage.com and make links in downloaded  HTML/CSS to point to local files.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;If you want to mirror only a part of website say 2014 November archives only, then you can pass no-parent argument.&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;wget --recursive --page-requisites --convert-links --no-parent www.avilpage.com/2014/11/&lt;br&gt;#wget -rpknp www.avilpage.com/2014/11&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;This downloads all the urls that follow 2014/11.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;In addition to that there are a hell lot of options you can pass like number of retries, time to wait, lot of HTTP options, FTP options and so on.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;2. Serving The Mirror Website:&lt;/h3&gt;&lt;div&gt;If you are familiar with Python, you might have heard of http.server. With a single command it starts running a basic web server. If you run the following command, &lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;python -m http.server 8000  #Python 3&lt;br&gt;or&lt;br&gt;python -m SimpleHTTPServer 8000  #Python 2&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;it starts serving files on port 8000. If you are on LAN, all others can access this mirrored website from their browser by specifying the IP &amp;amp; PORT. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;However this is just a basic server and not suitable for deployment. For that you can use Apache or Nginx to serve website.&lt;/div&gt;&lt;div&gt;&lt;br&gt;As wget fetches pages, start server. While wget is downloading the pages, you can browse through the downloaded pages. &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>linux</category><category>python</category><guid>https://avilpage.com/2014/11/mirror-website-quickly.html</guid><pubDate>Sat, 29 Nov 2014 02:47:00 GMT</pubDate></item><item><title>[Telugu] యండమూరి అంతర్ముఖం సినిమా</title><link>https://avilpage.com/2014/11/yandamoori-antharmukham-movie-novel.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;తెలుగు పుస్తకాలు, నవలలు చదివేవారు యండమూరి రాసిన  " అంతర్ముఖం " నవల పేరు విని వుంటారు. కాని యండమూరి ఆ పుస్తకాన్ని సినిమా గా తీసినట్లు చాల మందికి తెలియదు. ఈ సినిమా  YouTube లో అప్లోడ్ చేసారు. IMHO, సినిమా క్వాలిటీ,  ఆక్టర్స్ వగైరా వగైరా ఏమి బాగలెవు.&lt;br&gt;&lt;br&gt;&lt;iframe allowfullscreen="" frameborder="0" height="350" src="//www.youtube.com/embed/THp_gSG9xng" width="700"&gt;&lt;/iframe&gt;&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;iframe allowfullscreen="" frameborder="0" height="350" src="//www.youtube.com/embed/-XjaibkKv_4" width="700"&gt;&lt;/iframe&gt; &lt;br&gt;&lt;div&gt;&lt;iframe allowfullscreen="" frameborder="0" height="350" src="//www.youtube.com/embed/hI92SXfGUII" width="700"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>telugu</category><guid>https://avilpage.com/2014/11/yandamoori-antharmukham-movie-novel.html</guid><pubDate>Wed, 26 Nov 2014 13:38:00 GMT</pubDate></item><item><title>Split Video From Command Line Using FFmpeg</title><link>https://avilpage.com/2014/11/linux-splitting-required-portion-of.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I was writing a post about You Dont Mess With Zohan movie and I had to split a 50 second video from it.&lt;br&gt;&lt;br&gt;I have Vlc installed, so I enabled to view the advanced controls and recorded the required portion.&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-_MuvXa5Bpko/VHDkXMqmo1I/AAAAAAAANWs/uUuOBr2nyL0/s1600/split-video-ubuntu-command2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-_MuvXa5Bpko/VHDkXMqmo1I/AAAAAAAANWs/uUuOBr2nyL0/s1600/split-video-ubuntu-command2.png" height="296" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/--xxTZT9RnoQ/VHDkW53b9JI/AAAAAAAANWo/tS_bsqHu5eY/s1600/split-video-ubuntu-command.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/--xxTZT9RnoQ/VHDkW53b9JI/AAAAAAAANWo/tS_bsqHu5eY/s1600/split-video-ubuntu-command.png" height="139" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;Once it is done, I played it back,  but the audio and video are not syncing. I tried again and the same thing happened again.&lt;br&gt;&lt;br&gt;This is the video splitted with Vlc.&lt;br&gt;&lt;br&gt;&lt;div style="text-align: center;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/DJOlOELHhtM/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://youtube.googleapis.com/v/DJOlOELHhtM&amp;amp;source=uds"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="350" src="https://youtube.googleapis.com/v/DJOlOELHhtM&amp;amp;source=uds" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;/div&gt;Next, I splitted video with ffmpeg using this command.&lt;br&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;ffmpeg -i input.mp4 -vcodec copy -acodec copy -ss 01:20:12 -t 00:50:00 out.mp4&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;I splitted correctly and audio/video are synced perfectly well. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;This video is split with ffmpeg.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/P0TNsJubS3M/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://youtube.googleapis.com/v/P0TNsJubS3M&amp;amp;source=uds"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="350" src="https://youtube.googleapis.com/v/P0TNsJubS3M&amp;amp;source=uds" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>command-line</category><guid>https://avilpage.com/2014/11/linux-splitting-required-portion-of.html</guid><pubDate>Sun, 23 Nov 2014 13:05:00 GMT</pubDate></item><item><title>What Is The Area Code Of Amman?</title><link>https://avilpage.com/2014/11/mess-zohan-area-code-amman-transcript.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;In the movie, You Don't Mess With Zohan, these guys sitting at a dining table, try to call Phantom. One of the guy asks other for area code of Amman where Phantom lives. Here is the scene.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/P0TNsJubS3M/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://youtube.googleapis.com/v/P0TNsJubS3M&amp;amp;source=uds"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="350" src="https://youtube.googleapis.com/v/P0TNsJubS3M&amp;amp;source=uds" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;Here is the transcript:&lt;br&gt;&lt;i&gt;&lt;br&gt;&lt;/i&gt;&lt;i&gt;What is area code of Aman? &lt;/i&gt;&lt;br&gt;&lt;i&gt;&lt;br&gt;&lt;/i&gt;&lt;i&gt;sifr (0) wahid (1) wahid (1).&lt;/i&gt;&lt;br&gt;&lt;i&gt;arba'a (4) khamsa (5) talaata (3).&lt;/i&gt;&lt;br&gt;&lt;i&gt;khamsa (5) khamsa (5) sifr (0) sifr (0).&lt;/i&gt;&lt;br&gt;&lt;i&gt;saba'a (7) saba'a (7).&lt;/i&gt;&lt;br&gt;&lt;i&gt;sitta (6) talaata (3) arba'a (4) sitta (6).&lt;/i&gt;&lt;br&gt;&lt;i&gt;wahid (1).&lt;/i&gt;&lt;br&gt;&lt;i&gt;arba'a (4).&lt;/i&gt;&lt;br&gt;&lt;i&gt;sifr (0).&lt;/i&gt;&lt;br&gt;&lt;i&gt;saba'a (7).&lt;/i&gt;&lt;br&gt;&lt;i&gt;talaata (3) arba'a (4) khamsa (5).&lt;/i&gt;&lt;br&gt;&lt;br&gt;So the area code of amman is: 011453550077634561407345!&lt;br&gt;&lt;br&gt;If you want to learn arabic numerals this will help.&lt;br&gt;sifr - 0&lt;br&gt;wahid- 1&lt;br&gt;itnayn - 2&lt;br&gt;talaata - 3&lt;br&gt;arba'a - 4&lt;br&gt;khamsa - 5&lt;br&gt;sitta - 6&lt;br&gt;saba'a - 7&lt;br&gt;tamaanya - 8&lt;br&gt;tisa'a - 9&lt;br&gt;&lt;div&gt;&lt;br&gt;Source: &lt;a href="https://answers.yahoo.com/question/index?qid=20080924093624AAAuYPf" target="_blank"&gt;Yahoo Answers&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><guid>https://avilpage.com/2014/11/mess-zohan-area-code-amman-transcript.html</guid><pubDate>Sun, 23 Nov 2014 12:57:00 GMT</pubDate></item><item><title>Unix Timestamp, UTC And Their Conversions In Python</title><link>https://avilpage.com/2014/11/python-unix-timestamp-utc-and-their.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Coordinated Universal Time(UTC):&lt;/h4&gt;
&lt;p&gt;It is the primary time standard by which the world regulates clocks and time. To get current UTC time in Python, we can use &lt;code&gt;datetime&lt;/code&gt; module.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;datetime&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2014&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34435&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Unix time / POSIX time / Epoch time:&lt;/h4&gt;
&lt;p&gt;It is a system for describing instants in time, defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, not counting leap seconds. To get Unix timestamp, we can use &lt;code&gt;time&lt;/code&gt; module.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="mf"&gt;1416667432.5664258&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="mi"&gt;1416667766&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With Pyhon 3.4, we can directly get timestamp from UTC.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;In [13]: datetime.datetime.utcnow().timestamp()
Out[13]: 1416649608.58369
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Conversions:&lt;/h4&gt;
&lt;p&gt;To convert Unix timestamp to UTC we can use &lt;code&gt;utcfromtimestamp&lt;/code&gt; function.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcfromtimestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1416668401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2014&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To convert UTC time object to Unix time, we can use &lt;code&gt;strftime&lt;/code&gt; function.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="s1"&gt;'1416668938'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, we can use &lt;code&gt;calendar.timegen&lt;/code&gt; function.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;calendar&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timegm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utctimetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;Out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="mi"&gt;1416669150&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>linux</category><category>python</category><guid>https://avilpage.com/2014/11/python-unix-timestamp-utc-and-their.html</guid><pubDate>Sat, 22 Nov 2014 12:56:00 GMT</pubDate></item><item><title>[Git] Updating Cloned/Forked Repository On Local Machine and GitHub!</title><link>https://avilpage.com/2014/11/git-updating-clonedforked-repository-on.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;If You have forked a GitHub repo, after a few days/months later and the original master repo might change. So, it is essential to update your forked repo to reflect those changes. One simple solution is, you can delete it and fork again. But, if you have made any changes then you need some other solution.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;Updating Cloned Repo On Local Machine:&lt;/h3&gt;If you have cloned the repo to your local machine, you can add the original GitHub repository as a "remote". Then you can fetch all the branches from that original repository, and rebase your work to continue working on the upstream version.&lt;br&gt;&lt;br&gt;From command line you can do this&lt;br&gt;&lt;br&gt;Add the remote, call it "original":&lt;br&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;git remote add original https://github.com/whoever/whatever.git&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Fetch all the branches of that remote into remote-tracking branches, such as original/master:&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;&lt;span style="background-color: transparent;"&gt;git fetch original&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Make sure that you're on your master branch:&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;&lt;span style="background-color: transparent;"&gt;git checkout master&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Rewrite your master branch so that any commits of yours that aren't already in upstream/master are replayed on top of that other branch:&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;&lt;span style="background-color: transparent;"&gt;git rebase original/master&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;If you don't want to rewrite the history of your master branch, (for example because other people may have cloned it) then you should merge it&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;&lt;span style="background-color: transparent;"&gt;git merge original/master&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;However, for making further pull requests that are as clean as possible, it's probably better to rebase.&lt;br&gt; If you've rebased your branch onto upstream/master you may need to force the push in order to push it to your own forked repository on GitHub. You'd do that with:&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="background-color: #eeffcc;"&gt;&lt;pre style="border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(170, 204, 153); font-family: monospace, sans-serif; font-size: 15px; line-height: 18.5279998779297px; overflow-x: auto; overflow-y: hidden; padding: 5px;"&gt;&lt;span style="background-color: transparent;"&gt;git push -f origin master&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;Updating Forked Repo On GitHub:&lt;/h3&gt;If you have forked the repo on GitHub, then you can update it with web interface&lt;br&gt;&lt;br&gt;Go to your fork and issue a Pull Request.&lt;br&gt;By default this will be your fork on the right (head repo) requesting to push its commits and changes to the original repo (base repo) on the left.&lt;br&gt;Click the drop down for both base repo and head repo and select each other's repos. You want yours listed on the left (accepting changes) while the original repository is on the right (the one with changes to push). As illustrated in this image:&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://i.stack.imgur.com/qy04n.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://i.stack.imgur.com/qy04n.png" height="172" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;Send the pull request. If your fork has not had any changes, you should be able to automatically accept the merge.&lt;br&gt;&lt;br&gt;If your code somehow conflicts or is not quite clean enough, then this will not work to update via the GitHub web interface and you will need grab the code and resolve any conflicts on your machine before pushing back to your fork.&lt;br&gt;&lt;br&gt;Sources: StackOverflow, WebApps&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>git</category><guid>https://avilpage.com/2014/11/git-updating-clonedforked-repository-on.html</guid><pubDate>Sat, 22 Nov 2014 03:56:00 GMT</pubDate></item><item><title>Automagically Reload Imports In iPython!</title><link>https://avilpage.com/2014/11/python-automagically-reload-imports-in.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;When using iPython, users can import required modules to test them. After importing them, if they get modified either by user or some other process, users have to reload it for futher usage.&lt;/p&gt;
&lt;p&gt;Depending on the Python version, appropriate &lt;code&gt;reload&lt;/code&gt; function can reload modules.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Python 2.x&lt;/span&gt;
&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;imp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.0–3.3&lt;/span&gt;
&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;imp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.4+&lt;/span&gt;
&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;importlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of manually reloading, ipython has &lt;code&gt;autoreload&lt;/code&gt; extention which can auto reload modules. For that, load the extention and activate it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;load_ext&lt;/span&gt; &lt;span class="n"&gt;autoreload&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;autoreload&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This can be added to ipython config file so that autoreload gets activated, whenver it starts.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;ipython&lt;span class="w"&gt; &lt;/span&gt;profile&lt;span class="w"&gt; &lt;/span&gt;create
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This creates a default config file. Open config file which is present at &lt;code&gt;~/.ipython/profile_default/ipython_config.py&lt;/code&gt;  and add these two lines to it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteractiveShellApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'autoreload'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteractiveShellApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exec_lines&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'%autoreload 2'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that it won't reloads c extensions automatically.&lt;/p&gt;</description><category>python</category><guid>https://avilpage.com/2014/11/python-automagically-reload-imports-in.html</guid><pubDate>Wed, 19 Nov 2014 11:51:00 GMT</pubDate></item><item><title>Converting Strings To Correct Types In Python</title><link>https://avilpage.com/2014/11/python-converting-string-type-objects.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I was writing custom template tags for one of my Django package. I came across a situation where I had lists in string format. I need to convert them into lists.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;temp_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'[345, 3, 456, 45]'&lt;/span&gt;
&lt;span class="n"&gt;required_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are two methods to get this job done.&lt;/p&gt;
&lt;h4&gt;ast.literal_eval:&lt;/h4&gt;
&lt;p&gt;This can be used to evaluate  strings containing Python values from untrusted sources without parsing values.
import ast
ast.literal_eval(temp_str)&lt;/p&gt;
&lt;h4&gt;json.loads:&lt;/h4&gt;
&lt;p&gt;This is used to deserialize a string to python object using a conversion table.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;These&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt; &lt;span class="n"&gt;come&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handy&lt;/span&gt; &lt;span class="n"&gt;whenever&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;their&lt;/span&gt; &lt;span class="n"&gt;correct&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;
&lt;span class="n"&gt;obj_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'hello'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'3.64'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'-1'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can convert them to their corresponding types using these functions.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;literal_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;They yield a objects of corresponding types
new_obj_list = ['hello', 3, 3.64, -1]&lt;/p&gt;</description><category>python</category><guid>https://avilpage.com/2014/11/python-converting-string-type-objects.html</guid><pubDate>Mon, 17 Nov 2014 14:10:00 GMT</pubDate></item><item><title>Scaling Celery - Sending Tasks To Remote Machines</title><link>https://avilpage.com/2014/11/scaling-celery-sending-tasks-to-remote.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;h4 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.25em; line-height: 1.4; margin-bottom: 16px; margin-top: 1em; position: relative;"&gt;
    Celery:&lt;/h4&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    Celery is a Python package which implements a task queue mechanism with a foucs on real-time processing, while also supporting task scheduling.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    It has 3 main components.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;strong style="box-sizing: border-box;"&gt;Celery Application(or Client):&lt;/strong&gt; It is responsible for adding tasks to the queue.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;strong style="box-sizing: border-box;"&gt;Celery Worker(or Server):&lt;/strong&gt; It is responsible for executing the tasks given to it.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;strong style="box-sizing: border-box;"&gt;Broker:&lt;/strong&gt; It is responsible for transporting messages between client and server.
    &lt;/div&gt;

    &lt;h4 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.25em; line-height: 1.4; margin-bottom: 16px; margin-top: 1em; position: relative;"&gt;
    &lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#what-you-should-know" id="user-content-what-you-should-know" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1.2; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;" name="user-content-what-you-should-know"&gt;&lt;/a&gt;What You Should Know:&lt;/h4&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    You should know basics of Celery and you should be familiar with
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    creating celery tasks
    &lt;/div&gt;

    &lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; celery &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; Celery&lt;br&gt;&lt;br&gt;app &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; Celery(&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;tasks&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;backend&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;amqp&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;br&gt;                      &lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;broker&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;amqp://&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;ip&amp;gt;/&amp;lt;vhost&amp;gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;@app.task&lt;/span&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;add&lt;/span&gt;(&lt;span class="pl-smi" style="box-sizing: border-box;"&gt;x&lt;/span&gt;, &lt;span class="pl-smi" style="box-sizing: border-box;"&gt;y&lt;/span&gt;):&lt;br&gt;    &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;return&lt;/span&gt; x &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;+&lt;/span&gt; y
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    adding tasks to a queue,
    &lt;/div&gt;

    &lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

add.apply_async(&lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;args&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt;[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;,&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;])
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    and consuming tasks with a worker
    &lt;/div&gt;

    &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

celery worker -A my_app -l info
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    If your tasks doesn't need much system resources, you can setup all of them in the same machine. But, if you have a lot of jobs which consume resources,
    then you need to spread them out in several machines.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    In this tutorial lets move our celery workers into a remote machine keeping client and broker in same machine.
    &lt;/div&gt;

    &lt;h4 style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.25em; line-height: 1.4; margin-bottom: 16px; margin-top: 1em; position: relative;"&gt;
    &lt;a aria-hidden="true" class="anchor" href="http://localhost:6419/#sending-tasks-to-another-machine" id="user-content-sending-tasks-to-another-machine" style="box-sizing: border-box; color: #4078c0; cursor: pointer; display: block; left: 0px; line-height: 1.2; margin-left: -30px; padding-left: 30px; padding-right: 6px; position: absolute; text-decoration: none; top: 0px;" name="user-content-sending-tasks-to-another-machine"&gt;&lt;/a&gt;Sending Tasks To Another Machine:&lt;/h4&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;strong style="box-sizing: border-box;"&gt;On Machine A:&lt;/strong&gt;
    &lt;/div&gt;

    &lt;ol style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px; margin-top: 0px; padding: 0px 0px 0px 2em;"&gt;
    &lt;li style="box-sizing: border-box;"&gt;
        &lt;div style="box-sizing: border-box; margin-bottom: 16px; margin-top: 16px;"&gt;
          Install Celery &amp;amp; RabbitMQ.
        &lt;/div&gt;
      &lt;/li&gt;

      &lt;li style="box-sizing: border-box;"&gt;
        &lt;div style="box-sizing: border-box; margin-bottom: 16px; margin-top: 16px;"&gt;
          Configure RabbitMQ so that Machine B can connect to it.
        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

&lt;span class="pl-c" style="box-sizing: border-box; color: #969896;"&gt;# add new user&lt;/span&gt;&lt;br&gt;sudo rabbitmqctl add_user &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;user&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;password&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="pl-c" style="box-sizing: border-box; color: #969896;"&gt;# add new virtual host&lt;/span&gt;&lt;br&gt;sudo rabbitmqctl add_vhost &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;vhost_name&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="pl-c" style="box-sizing: border-box; color: #969896;"&gt;# set permissions for user on vhost&lt;/span&gt;&lt;br&gt;sudo rabbitmqctl set_permissions -p &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;vhost_name&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;user&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;.*&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;.*&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;.*&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="pl-c" style="box-sizing: border-box; color: #969896;"&gt;# restart rabbit&lt;/span&gt;&lt;br&gt;sudo rabbitmqctl restart
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;ol style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px; margin-top: 0px; padding: 0px 0px 0px 2em;"&gt;
    &lt;li style="box-sizing: border-box;"&gt;Create a new file remote.py with a simple task. Here we have broker installed in machine A. So give ip address of
    machine 1 in broker url option.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; celery &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; Celery&lt;br&gt;&lt;br&gt;app &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt; Celery(&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;tasks&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;backend&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;amqp&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;br&gt;                      &lt;span class="pl-v" style="box-sizing: border-box; color: #ed6a43;"&gt;broker&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;=&lt;/span&gt;&lt;span class="pl-s" style="box-sizing: border-box; color: #183691;"&gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;amqp://&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;ip&amp;gt;/&amp;lt;vhost&amp;gt;&lt;span class="pl-pds" style="box-sizing: border-box;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br&gt;&lt;br&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;def&lt;/span&gt; &lt;span class="pl-en" style="box-sizing: border-box; color: #795da3;"&gt;add&lt;/span&gt;(&lt;span class="pl-smi" style="box-sizing: border-box;"&gt;x&lt;/span&gt;, &lt;span class="pl-smi" style="box-sizing: border-box;"&gt;y&lt;/span&gt;):&lt;br&gt;     &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;return&lt;/span&gt; x &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;+&lt;/span&gt; y
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;ol style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px; margin-top: 0px; padding: 0px 0px 0px 2em;"&gt;
    &lt;li style="box-sizing: border-box;"&gt;Now we have everything setup on machine A. We can now put some tasks in queue.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class="highlight highlight-source-python" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;]: &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;from&lt;/span&gt; remote &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;import&lt;/span&gt; add&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;]: add.delay(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;1&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;]: &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;AsyncResult: &lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;3eb96a11&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;aa61&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;46d3&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;9b9d&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;e0e1703438d0&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;]: b.delay(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;2&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;]: &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;AsyncResult: ec40db1a&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;a43c&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;4486&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;9530&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;0a3153fe1380&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;In [&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;4&lt;/span&gt;]: b.delay(&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;3&lt;/span&gt;, &lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;4&lt;/span&gt;)&lt;br&gt;Out[&lt;span class="pl-c1" style="box-sizing: border-box; color: #0086b3;"&gt;4&lt;/span&gt;]: &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;lt;&lt;/span&gt;AsyncResult: ca53a4c7&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;061b&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;408e&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;82ee&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;-&lt;/span&gt;&lt;span class="pl-ii" style="background-color: #b52a1d; box-sizing: border-box; color: #f8f8f8;"&gt;86c2d43d21a0&lt;/span&gt;&lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    Everything is setup on machine A. Now lets get into machine B.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;strong style="box-sizing: border-box;"&gt;On Machine B:&lt;/strong&gt;
    &lt;/div&gt;

    &lt;ol style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px; margin-top: 0px; padding: 0px 0px 0px 2em;"&gt;
    &lt;li style="box-sizing: border-box;"&gt;Install Celery.&lt;/li&gt;

      &lt;li style="box-sizing: border-box;"&gt;
        &lt;div style="box-sizing: border-box; margin-bottom: 16px; margin-top: 16px;"&gt;
          Copy remote.py file from machine A to this machine.
        &lt;/div&gt;
      &lt;/li&gt;

      &lt;li style="box-sizing: border-box;"&gt;
        &lt;div style="box-sizing: border-box; margin-bottom: 16px; margin-top: 16px;"&gt;
          Run a worker to consume the tasks
        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

celery worker -l info -A remote
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    As soon as you launch the worker, you will receive the tasks you queued up and gets executed immediately.
    &lt;/div&gt;

    &lt;div class="highlight highlight-source-shell" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    &lt;pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; overflow: auto; padding: 16px; word-break: normal; word-wrap: normal;"&gt;

[2014-11-09 00:01:19,168: INFO/MainProcess] Received task: remote.add[c2d2bb27-ff5f-47da-b2b9-6fb11669ee1a]&lt;br&gt;[2014-11-09 00:01:19,170: INFO/MainProcess] Received task: remote.add[8daa1a5c-17d0-46dc-9c93-faf7fbeccdd9]&lt;br&gt;[2014-11-09 00:01:19,172: INFO/MainProcess] Received task: remote.add[79603d15-24f1-43f8-b8b7-525b7cd4b9a2]&lt;br&gt;[2014-11-09 00:01:19,401: INFO/MainProcess] Task remote.add[8daa1a5c-17d0-46dc-9c93-faf7fbeccdd9] succeeded &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; 0.226168102003s: 3&lt;br&gt;[2014-11-09 00:01:19,462: INFO/MainProcess] Task remote.add[c2d2bb27-ff5f-47da-b2b9-6fb11669ee1a] succeeded &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; 0.286503815001s: 5&lt;br&gt;[2014-11-09 00:01:19,464: INFO/MainProcess] Task remote.add[79603d15-24f1-43f8-b8b7-525b7cd4b9a2] succeeded &lt;span class="pl-k" style="box-sizing: border-box; color: #a71d5d;"&gt;in&lt;/span&gt; 0.288741396998s: 7
&lt;/pre&gt;
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    This is just a simple guide on how to send tasks to remote machines.
    &lt;/div&gt;

    &lt;div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;"&gt;
    Depending on your need, you might have to set up a cluster of servers and route tasks accordingly to scale.
    &lt;/div&gt;

  &lt;/div&gt;</description><category>celery</category><category>django</category><category>python</category><guid>https://avilpage.com/2014/11/scaling-celery-sending-tasks-to-remote.html</guid><pubDate>Sun, 09 Nov 2014 08:35:00 GMT</pubDate></item><item><title>Pandoc: Best Way To Convert Markdown to reStructuredText!</title><link>https://avilpage.com/2014/11/pandoc-best-way-to-convert-markdown-to.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I wrote a simple readme to one of my Python package &lt;a href="http://www.github.com/fadapa/fadapa" target="_blank"&gt;Fadapa&lt;/a&gt;. I built the package using setuptools. In setup.py file, for long_description field I just read README.md file and  assigned it. After uploading the package to &lt;a href="https://pypi.python.org/pypi/fadapa/" target="_blank"&gt;PyPi&lt;/a&gt;, I saw the page and found that PyPi doesn't support Markdown format. So I had to change it to reStructuredText.&lt;br&gt;&lt;br&gt;Pandoc is the best tool available to convert markup formats. It supports a lot of formats and you can convert it to any format you want.&lt;br&gt;&lt;br&gt;If you have a few documents to convert, you can &lt;a href="http://johnmacfarlane.net/pandoc/try/" target="_blank"&gt;convert them online&lt;/a&gt;. You can also install in in your system if you want to convert a lot files. Instructions on how to install on various &lt;a href="http://johnmacfarlane.net/pandoc/installing.html" target="_blank"&gt;operating systems is give here&lt;/a&gt;.&lt;br&gt;&lt;br&gt;For ubuntu you can install by&lt;br&gt;&lt;div style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 17px; line-height: 20.1599979400635px;" width="100px"&gt;&lt;pre class="literal-block" style="background-color: #e0e0ff; border-bottom-left-radius: 0.5em; border-bottom-right-radius: 0.5em; border-top-left-radius: 0.5em; border-top-right-radius: 0.5em; border: thin solid rgb(170, 170, 255); font-size: 14px; line-height: 17.8231201171875px; margin-left: 2em; margin-right: 2em; padding: 10px;"&gt;sudo apt-get install pandoc   &lt;/pre&gt;&lt;/div&gt;Then you can convert files using&lt;br&gt;&lt;div style="background-color: white;" width="100px"&gt;&lt;pre class="literal-block" style="background-color: #e0e0ff; border-bottom-left-radius: 0.5em; border-bottom-right-radius: 0.5em; border-top-left-radius: 0.5em; border-top-right-radius: 0.5em; border: thin solid rgb(170, 170, 255); margin-left: 2em; margin-right: 2em; padding: 10px;"&gt;&lt;span style="color: #666666;"&gt;&lt;span style="font-size: 14px; line-height: 17.8231201171875px;"&gt;pandoc readme.md --from markdown --to rst -s -o readme.rst&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;This converts readme.md to readme.rst.&lt;br&gt;&lt;br&gt;&lt;a href="https://github.com/bebraw/pypandoc" target="_blank"&gt;Pypandoc&lt;/a&gt; is a simple python wrapper for pandoc. Using that also, you can convert files.&lt;br&gt;&lt;br&gt;Install it using pip&lt;br&gt;&lt;div style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 17px; line-height: 20.1599979400635px;" width="100px"&gt;&lt;pre class="literal-block" style="background-color: #e0e0ff; border-bottom-left-radius: 0.5em; border-bottom-right-radius: 0.5em; border-top-left-radius: 0.5em; border-top-right-radius: 0.5em; border: thin solid rgb(170, 170, 255); font-size: 14px; line-height: 17.8231201171875px; margin-left: 2em; margin-right: 2em; padding: 10px;"&gt;pip install pypandoc&lt;/pre&gt;&lt;/div&gt;and then to convert files just do&lt;br&gt;&lt;div style="background-color: white;" width="100px"&gt;&lt;pre class="literal-block" style="background-color: #e0e0ff; border-bottom-left-radius: 0.5em; border-bottom-right-radius: 0.5em; border-top-left-radius: 0.5em; border-top-right-radius: 0.5em; border: thin solid rgb(170, 170, 255); margin-left: 2em; margin-right: 2em; padding: 10px;"&gt;&lt;span style="color: #666666;"&gt;&lt;span style="font-size: 14px; line-height: 17.8231201171875px;"&gt;import pypandoc&lt;br&gt;output = pypandoc.convert('somefile.md', 'rst')&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #666666; font-family: Trebuchet MS, Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 17.8231201171875px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br&gt;Update: There is an &lt;a href="https://bitbucket.org/pypa/pypi/issue/148/support-markdown-for-readmes" target="_blank"&gt;feature request with pull request&lt;/a&gt; to add support for Markdown for PyPi.&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>python</category><guid>https://avilpage.com/2014/11/pandoc-best-way-to-convert-markdown-to.html</guid><pubDate>Tue, 04 Nov 2014 12:34:00 GMT</pubDate></item><item><title>Start Up Job Boards In India</title><link>https://avilpage.com/2014/11/how-to-get-job-in-start-up-in-india.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Working with start ups is not only &lt;a href="http://www.zdnet.com/in/why-working-for-startups-is-worth-it-7000023025/" target="_blank"&gt;exciting &amp;amp; challenging&lt;/a&gt; but &lt;a href="http://www.quora.com/What-is-it-like-to-work-at-Social-Cops" target="_blank"&gt;its a lot of fun&lt;/a&gt; and there are lot of reasons why &lt;a href="http://yourstory.com/2014/05/working-with-startups/" target="_blank"&gt;working with a start up is the best thing you will ever do&lt;/a&gt;. &lt;br&gt;&lt;br&gt;While hunting for a start up job in Bangalore, these are some good job boards I came across.&lt;br&gt;&lt;br&gt;1. &lt;a href="https://hasjob.co/" target="_blank"&gt;Has Job&lt;/a&gt;&lt;br&gt;&lt;br&gt;2. &lt;a href="http://jobs.yourstory.com/jobs/listing" target="_blank"&gt;Your Story Jobs&lt;/a&gt;&lt;br&gt;&lt;br&gt;3. &lt;a href="http://themorpheus.com/startup-jobs/" target="_blank"&gt;Startup Jobs @ The Morpheus&lt;/a&gt;&lt;br&gt;&lt;br&gt;4. &lt;a href="http://jobs.nextbigwhat.com/" target="_blank"&gt;NextBigWhat Job Board&lt;/a&gt;&lt;br&gt;&lt;br&gt;5. &lt;a href="https://groups.google.com/forum/#!forum/headstart-network" target="_blank"&gt;HeadStart Network&lt;/a&gt;&lt;br&gt;&lt;br&gt;6. &lt;a href="http://job.venturehire.co/" target="_blank"&gt;Venture Hire&lt;/a&gt;&lt;br&gt;&lt;br&gt;7. &lt;a href="http://dreamstarts.in/" target="_blank"&gt;Dream Starts&lt;/a&gt;&lt;br&gt;&lt;br&gt;8. &lt;a href="http://blrstartups.com/" target="_blank"&gt;Bangalore Startups&lt;/a&gt;&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;9. &lt;a href="http://www.f6s.com/jobs" target="_blank"&gt;f6s Jobs&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>bangalore</category><category>startups</category><guid>https://avilpage.com/2014/11/how-to-get-job-in-start-up-in-india.html</guid><pubDate>Mon, 03 Nov 2014 10:53:00 GMT</pubDate></item><item><title>Django Tips &amp; Tricks #1 - Shell Aliases For Python/Django Developers</title><link>https://avilpage.com/2014/10/useful-shell-aliases-for-python-and.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Developers and hackers prefer using terminal and spend a lot of time on it. Instead of typing long commands over and over, they can be aliased to shortnames. The shell builtin alias allows users to set aliases.&lt;/p&gt;
&lt;p&gt;One of the most used command while setting up development environment is &lt;code&gt;pip install -r requirements.txt&lt;/code&gt; This can be aliased to &lt;code&gt;pir&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now to install requirements, type &lt;code&gt;pir&lt;/code&gt; and pressing enter. Here are some other aliases related to python which will be useful on a daily basis.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'python'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ipy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ipython'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;py3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'python3'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ipy3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ipython3'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;jn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'jupyter notebook'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;wo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'workon'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pip freeze | sort'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pip install'&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pun&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pip uninstall'&lt;/span&gt;

&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;drs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py runserver"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;drp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py runserverplus"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;drps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py runserverplus --print-sql"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dsh&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py shell"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dsp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py shell_plus"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dsps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py shell_plus --print-sql"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dsm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py schemamigration"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py migrate"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dmm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py makemigrations"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ddd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py dumpdata"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dld&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py loaddata"&lt;/span&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python manage.py test"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just add the above aliases to your &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt;. That's it. Hpy alsng!&lt;/p&gt;</description><category>command-line</category><category>django</category><category>django-tips-tricks</category><category>python</category><guid>https://avilpage.com/2014/10/useful-shell-aliases-for-python-and.html</guid><pubDate>Sat, 25 Oct 2014 12:57:00 GMT</pubDate></item><item><title>A Better Way To Take Screenshots Of Movies With Subtitles</title><link>https://avilpage.com/2014/10/a-better-way-to-take-screenshots-of.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I take a lot of screenshots(just press &lt;b&gt;SHIFT + S&lt;/b&gt; or select &lt;b&gt;Take screenshot&lt;/b&gt; from &lt;b&gt;Video&lt;/b&gt; drop down menu) when I am watching movies. Few days back I was watching The Matrix and I wanted a take screenshot of this quote.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-STJgj5EysE4/VEFYFWaCEkI/AAAAAAAANQs/u6VHGFXRq-E/s1600/movie-screenshots-tips.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-STJgj5EysE4/VEFYFWaCEkI/AAAAAAAANQs/u6VHGFXRq-E/s1600/movie-screenshots-tips.png" height="360" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-DgJduy6SVK8/VEFYFVzLTlI/AAAAAAAANQo/AG8Rp3msV6s/s1600/movie-screenshots-vlc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-DgJduy6SVK8/VEFYFVzLTlI/AAAAAAAANQo/AG8Rp3msV6s/s1600/movie-screenshots-vlc.png" height="360" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;However the entire quote is present in two different frames. I used to use image editor and join those two images and keep them in my screenshots folder.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Today as I was thinking about a better solution for this. I got this idea of editing subtitles. I opened the subtitles files and edited this part  &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;pre class="lang-py prettyprint prettyprinted" style="background: rgb(238, 238, 238); border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.8048000335693px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"&gt;&lt;code style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"&gt;&lt;span style="background-color: transparent; font-family: 'Times New Roman'; font-size: small; line-height: normal; white-space: normal;"&gt;753&lt;/span&gt;&lt;span class="kwd" style="background: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;01:06:45,251 --&amp;gt; 01:06:47,085&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;To deny our own impulses...&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;754&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;01:06:47,336 --&amp;gt; 01:06:50,463&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;... is to deny the very thing&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;that makes us human. &lt;/div&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;and changed to this&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="lang-py prettyprint prettyprinted" style="background: rgb(238, 238, 238); border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.8048000335693px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"&gt;&lt;code style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"&gt;&lt;span class="kwd" style="background: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;753&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;01:06:45,251 --&amp;gt; 01:06:47,085&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;To deny our own impulses is to deny the very thing&lt;/div&gt;&lt;br&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; line-height: normal; white-space: normal;"&gt;&lt;br&gt;that makes us human. &lt;/div&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;which made it possible to capture the entire quote in a single frame.&lt;br&gt;&lt;br&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Wmjkh9aGvrQ/VEFb6yB8RHI/AAAAAAAANQ8/zsWhlYf3vjc/s1600/movie-tricks-screenshots.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Wmjkh9aGvrQ/VEFb6yB8RHI/AAAAAAAANQ8/zsWhlYf3vjc/s1600/movie-tricks-screenshots.png" height="358" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;Of course this is not the best method but it is far better than editing and joining couple of images.&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>how-to</category><category>vlc</category><guid>https://avilpage.com/2014/10/a-better-way-to-take-screenshots-of.html</guid><pubDate>Fri, 17 Oct 2014 12:45:00 GMT</pubDate></item><item><title>I Found A Purse Near Dairy Circle, Bangalore!</title><link>https://avilpage.com/2014/10/i-found-purse-near-dairy-circle.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I was going to Dairy circle yesterday evening. Near to the bus stop  I  found  a purse. A lot of people were standing and passing by but no one noticed it. I just looked around to see if any one is searching for it. But no one was there. I checked the contents to see if any number or any information is available to call the owner of the purse.&lt;br&gt;&lt;br&gt;Here are the contents of the purse:&lt;br&gt;&lt;br&gt;1. Bus ticket from Chennai to Bangalore&lt;br&gt;2. A shop's visiting card&lt;br&gt;3. A hundred rupee note&lt;br&gt;4. An old ten rupee note&lt;br&gt;5. Some change.&lt;br&gt;6. 3 photos&lt;br&gt;7. A SIM card&lt;br&gt;&lt;br&gt;There was number written on the purse. I tried to call that number but it was not reachable and the SIM card also not working.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-zSWY_oTvJR4/VDq6vn7FWMI/AAAAAAAANQI/m04e5LDEtLU/s1600/bangalore-found-purse.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-zSWY_oTvJR4/VDq6vn7FWMI/AAAAAAAANQI/m04e5LDEtLU/s1600/bangalore-found-purse.jpg" height="480" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;</description><category>bangalore</category><guid>https://avilpage.com/2014/10/i-found-purse-near-dairy-circle.html</guid><pubDate>Sun, 12 Oct 2014 12:03:00 GMT</pubDate></item><item><title>How To Install Adobe Digital Editions On Ubuntu 14.04?</title><link>https://avilpage.com/2014/10/how-to-install-adobe-digital-editions.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Few days back, I rented an e-book from &lt;a href="http://www.avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html" target=""&gt;Kinige, a retailer of telugu print &amp;amp; ebooks&lt;/a&gt;. I thought I could read that book immediately on their website. But they offered a &lt;b&gt;.acsm &lt;/b&gt;&amp;amp; I had to install &lt;a href="http://www.adobe.com/solutions/ebook/digital-editions.html" target="_blank"&gt;ADE&lt;/a&gt;(Adobe Digital Editions) to read that book. Since ADE is not available for Linux platform, I had to install wine first and then install ADE from it.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;1. Installing Wine:&lt;/h3&gt;&lt;div&gt;&lt;a href="https://www.winehq.org/about/"&gt;Wine&lt;/a&gt;  is a compatibility layer capable of running Windows applications on several POSIX-compliant operating systems, such as Linux, Mac OSX, &amp;amp; BSD. The easiest way to install wine on Ubuntu 14.04 is from its PPA. Open the terminal and run these commands.&lt;/div&gt;&lt;pre class="lang-py prettyprint prettyprinted" style="background: rgb(238, 238, 238); border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.8048000335693px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"&gt;&lt;code style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"&gt;&lt;span class="pln" style="background: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"&gt;sudo add-apt-repository ppa:ubuntu-wine/ppa&lt;/span&gt;&lt;span class="pln" style="background: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"&gt;&lt;br&gt;sudo apt-get update&lt;br&gt;&lt;/span&gt;&lt;span class="kwd" style="background: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"&gt;sudo apt-get install wine1.7 winetricks &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;You can check if wine is installed correctly by typing &lt;span style="background-color: white; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 17.8048000335693px;"&gt; &lt;/span&gt;&lt;code style="background: rgb(238, 238, 238); border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.8048000335693px; margin: 0px; padding: 1px 5px; vertical-align: baseline; white-space: pre-wrap;"&gt;wine --version&lt;/code&gt;&lt;span style="background-color: white; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 17.8048000335693px;"&gt; &lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;2. Install ADE&lt;/h3&gt;Once you installed wine, you can easily install ADE. The current version is ADE 4.0 as of today(Oct 9th 2014). But only ADE 1.7 works on wine. So you have to download ADE 1.7. You can &lt;a href="https://drive.google.com/file/d/0B3vmn780gZJ9ZWowbEdabVBnRE0/view?usp=sharing"&gt;download it from here&lt;/a&gt;. Once you have downloaded that, you can just double click and install it just like windows.&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>how-to</category><category>tech</category><category>ubuntu</category><guid>https://avilpage.com/2014/10/how-to-install-adobe-digital-editions.html</guid><pubDate>Wed, 08 Oct 2014 11:14:00 GMT</pubDate></item><item><title>తెలుగు సాహిత్యం పైన చలం ప్రభావం!</title><link>https://avilpage.com/2014/10/influence-of-chalam-on-telugu-literature.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;చలం వల్ల తెలుగు సాహిత్యం లోను రచయతల్లోను వ్యక్తుల జీవితాల్లోను ఏం మార్పులు జరిగాయో అర్థం చేసుకోవటానికి ఈ ఒక్క పేరా చాలు.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-2UGjGTdJQQk/VDQoTV-PpJI/AAAAAAAANPw/ZoQwgc7Bswc/s1600/chalam-influence-telugu-literature.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-2UGjGTdJQQk/VDQoTV-PpJI/AAAAAAAANPw/ZoQwgc7Bswc/s1600/chalam-influence-telugu-literature.png" height="467" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;ఈ పేరా రంగనాయకమ్మ  గారి చలం సాహిత్యం నుండి తీసుకోబడింది. &lt;/div&gt;</description><category>chalam</category><guid>https://avilpage.com/2014/10/influence-of-chalam-on-telugu-literature.html</guid><pubDate>Tue, 07 Oct 2014 13:03:00 GMT</pubDate></item><item><title>Illumina BaseSpace WWDC - Bangalore</title><link>https://avilpage.com/2014/09/highlights-of-illumina-basespace-wwdc.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Illumina&lt;sup id="fnref:illumina"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/09/highlights-of-illumina-basespace-wwdc.html#fn:illumina"&gt;1&lt;/a&gt;&lt;/sup&gt; develops, manufactures and markets integrated systems for the analysis of genetic variation and biological function. BaseSpace&lt;sup id="fnref:bs"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/09/highlights-of-illumina-basespace-wwdc.html#fn:bs"&gt;2&lt;/a&gt;&lt;/sup&gt; is Illumina’s genomics computing environment for next-generation sequencing (NGS) data analysis.&lt;/p&gt;
&lt;p&gt;To teach developers, how to build and launch your own bioinformatics apps on BaseSpace, Illumina conducted a two day hands-on hackathon. Here is the summary of the event.&lt;/p&gt;
&lt;p&gt;Raymond Tecotzky provided a good overview of basespace, plugged in missing information in various situations. Most importanatly super charged participants &amp;amp; the team.&lt;/p&gt;
&lt;p&gt;James Hadfield &amp;amp; Ramesh Hariharan delivered good talks about their work on Genomics and their experience with Basespace.&lt;/p&gt;
&lt;p&gt;Sucheth Koppa provided a good overview of BaseSpace Onsite &amp;amp; how you can keep all data on-premises.&lt;/p&gt;
&lt;p&gt;Mayank Tyagi &amp;amp; his team stressing the importance of Docker, taught how to build apps on Basespace.  Hands-on hackathon &amp;amp; very informative.&lt;/p&gt;
&lt;p&gt;Along with talks, food, wine, t-shirt &amp;amp; USB Drive(16 GB) are also great.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://avilpage.com/images/illumina-basespace-wwdc.png" alt="Illumina BaseSpace WWDC - Bangalore" title="Illumina BaseSpace WWDC - Bangalore"&gt;&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:illumina"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Illumina,_Inc."&gt;https://en.wikipedia.org/wiki/Illumina,_Inc&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/09/highlights-of-illumina-basespace-wwdc.html#fnref:illumina" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:bs"&gt;
&lt;p&gt;&lt;a href="https://basespace.illumina.com"&gt;https://basespace.illumina.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/09/highlights-of-illumina-basespace-wwdc.html#fnref:bs" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>bangalore</category><category>bioinformatics</category><guid>https://avilpage.com/2014/09/highlights-of-illumina-basespace-wwdc.html</guid><pubDate>Tue, 30 Sep 2014 07:10:00 GMT</pubDate></item><item><title>Using Sourcegraph To Search Real Code!</title><link>https://avilpage.com/2014/09/using-sourcegraph-to-search-real-code.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h3 style="text-align: left;"&gt;What Is Sourcegraph Anyway?&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;i&gt;" Sourcegraph is a code search engine that lets you search across hundreds of thousands of libraries and browse code in the same way you can do in a great IDE. "&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.sourcegraph.com/" target="_blank"&gt;Sourcegraph&lt;/a&gt; is not the first code search engine ever built, neither it will be last, but it offers is completely different from all other code search engines like &lt;a href="http://nullege.com/" target="_blank"&gt;Nullege&lt;/a&gt;, &lt;a href="http://code.ohloh.net/" target="_blank"&gt;OpenHUB&lt;/a&gt;. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;Why Should You Care?&lt;/h3&gt;I will explain a few situations where it makes developers life a little bit easier.&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;1. Search Real Code:&lt;/h3&gt;&lt;div&gt;Sourcegraph helps you to quickly search open source projects &amp;amp; see realcode examples. Let's say I am using &lt;b&gt;&lt;a href="http://celeryproject.org/" target="_blank"&gt;Celery&lt;/a&gt; &lt;/b&gt;to schedule some tasks. I know there is &lt;b&gt;chord (&lt;/b&gt;a task that only executes after all of the tasks in a taskset has finished executing) but I don't know how to use it. I can use Sourcegraph to find &lt;b&gt;chord, &lt;/b&gt;look at its api, check out some real world examples. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Here it doesn't sound Sourcegraph is much useful because you can go through the documentation and you can get all the information about it. But you won't find a lot of real world examples in documentation.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Also if you learning about a new module, it will take a while to wrap your head and get used to that module. What you can do is browse through sourcegraph to understand the api &amp;amp; immediately check out some real code where other programmers have used it for various purposes. I feel this helps a lot to start using a new module and get used to it quickly.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;2. Bad Documented Libraries:&lt;/h3&gt;&lt;div&gt;There are tons of open source libraries &amp;amp; some of them have very good documentation. There are some good libraries which are documented badly or don't have documentation at all. It's a huge pain to to use a library with bad documentation. Here sourcegraph once again comes to rescue us by quickly navigating around the code. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;3. Chrome Extension:&lt;/h3&gt;&lt;div&gt;I spend significant time on Github browsing code. Sometimes I clone the repo and browse it on Emacs. But sometimes I just want to browse on Github itself. &lt;a href="https://chrome.google.com/webstore/detail/sourcegraph/dgjhfomjieaadpoljlnidmbgkdffpack/details" target="_blank"&gt;Sourcegraph has chrome extension&lt;/a&gt; which lets you browse code quickly on GitHub by making every identifer a jump-to-definition link. By the way if you are a using it please write a review.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-qj0OXkUqFdo/VBx4g58SAHI/AAAAAAAAKz4/z923a766610/s1600/sourcegraph-review-usage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-qj0OXkUqFdo/VBx4g58SAHI/AAAAAAAAKz4/z923a766610/s1600/sourcegraph-review-usage.png"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;That's if for now. I came across Sourcegraph a couple of weeks back. From then on I am using it almost everyday. Currently it supports only Python, Go, Ruby, Node.js. I hope it will support for other languages soon. What I mentioned here is just a little introduction. Check out ProTips, &lt;a href="https://sourcegraph.com/help/doc" target="_blank"&gt;Sourcegraph docs&lt;/a&gt; &amp;amp; &lt;a href="https://srclib.org/" target="_blank"&gt;srclib&lt;/a&gt;(a polyglot code analysis library, built with hackability in mind). If you are a Go programmer, read &lt;a href="https://leanpub.com/howdoiusesourcegraph" target="_blank"&gt;How do I use Sourcegraph with Go?&lt;/a&gt; (a short FREE ebook by Satish Talim).&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;div&gt;&lt;br class="Apple-interchange-newline"&gt;========================================================================&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.avilpage.com/search/label/chrome%20extensions"&gt;More Chrome Extensions&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><guid>https://avilpage.com/2014/09/using-sourcegraph-to-search-real-code.html</guid><pubDate>Fri, 19 Sep 2014 13:23:00 GMT</pubDate></item><item><title>Chrome Extensions For Efficient &amp; Productive Web Surfing</title><link>https://avilpage.com/2014/09/a-few-chrome-extensions-for-efficient.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div style="text-align: left;"&gt;I do use a lot of chrome extensions. Here are some of my favorite extensions which I use for everyday browsing.&lt;br&gt;&lt;br&gt;&lt;/div&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/adblock/gighmmpiobklfepjocnamgkkbiglidom" target="_blank"&gt;1. AdBlock&lt;/a&gt;&lt;/h4&gt;Blocks annoying ads all over the web.&lt;br&gt;&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb" target="_blank"&gt;2. Vimium&lt;/a&gt;&lt;/h4&gt;I love browsing web with just keyboard. If you are familiar with Vim, install it without any second thoughts. Vimium provides keyboard shortcuts for navigation and
    control in the spirit of Vim.&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;/h4&gt;
    &lt;div&gt;&lt;br&gt;&lt;/div&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/alexa-traffic-rank/cknebhggccemgcnbidipinkifmmegdel" target="_blank"&gt;3. Alexa Traffic Rank&lt;/a&gt;&lt;/h4&gt;If you are a webmaster or stataholic, you need this.&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;/h4&gt;
    &lt;div&gt;&lt;br&gt;&lt;/div&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/google-quick-scroll/okanipcmceoeemlbjnmnbdibhgpbllgc" target="_blank"&gt;4. Google Quick Scroll&lt;/a&gt;&lt;/h4&gt;If you have searched for something on Google and landed on a page with lot of text, it helps you jump directly to
    the relevant bits of a search result.&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;/h4&gt;
    &lt;div&gt;&lt;br&gt;&lt;/div&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/hover-zoom/nonjdcjchghhkdoolnlbekcfllmednbl" target="_blank"&gt;5. Hover Zoom&lt;/a&gt;&lt;/h4&gt;Simply enlarge thumbnails by hovering your mouse.&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;/h4&gt;
    &lt;div&gt;&lt;br&gt;&lt;/div&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/hoverreader/bgchppjofckmmlfpegeinpegcjmejnlk" target="_blank"&gt;6. HoverReader&lt;/a&gt;&lt;/h4&gt;While reading an article, if you encounter a hyperlink, peek into it by hovering the mouse.&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;/h4&gt;
    &lt;div&gt;&lt;br&gt;&lt;/div&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/magic-actions-for-youtube/abjcfabbhafbcdfjoecdgepllmpfceif" target="_blank"&gt;7. Magic Actions for YouTube&lt;/a&gt;&lt;/h4&gt;Auto HD, Ad Block, Cinema Mode, Mouse Wheel Volume Control and more magic actions for YouTube.&lt;br&gt;&lt;br&gt;
    &lt;h4 style="text-align: left;"&gt;8. &lt;a href="https://chrome.google.com/webstore/detail/readable-wikipedia/imoddojnfpdkpfiipadaibjplddaneka" style="text-decoration: line-through;" target="_blank"&gt;Readable Wikipedia&lt;/a&gt;  &lt;a href="https://chrome.google.com/webstore/detail/wikiwand-wikipedia-modern/emffkefkbkpkgpdeeooapgaicgmcbolj" target="_blank"&gt;WikiWand&lt;/a&gt;&lt;/h4&gt;Previously I used Readable Wiikpedia to read wiki articles.&lt;br&gt;But now I use WikiWand. It provides amazing look for our beloved Wikipedia.&lt;br&gt;&lt;br&gt;
    &lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/detail/autopagerize/igiofjhpmpihnifddepnpngfjhkfenbp" target="_blank"&gt;9. AutoPager Chrome&lt;/a&gt;&lt;/h4&gt;Scroll through paginated web pages.&lt;br&gt;&lt;br&gt;&lt;h4 style="text-align: left;"&gt;&lt;a href="https://chrome.google.com/webstore/search/auto%20save" target="_blank"&gt;10. DevTools Auto Save&lt;/a&gt;&lt;/h4&gt;Saves changes to your CSS and JS right from the browser. Comes in handy for web developers.&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://chrome.google.com/webstore/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall" target="_blank"&gt;11. OneTab&lt;/a&gt;&lt;/b&gt;:&lt;br&gt;Pull all tabs into single tab &amp;amp; save up to 95% memory and reduce tab clutter.&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://chrome.google.com/webstore/detail/javascript-popup-blocker/hiajdlfgbgnnjakkbnpdhmhfhklkbiol" target="_blank"&gt;12. Popup Blocker Pro&lt;/a&gt;&lt;/b&gt;:&lt;br&gt;Blocks all annoying popups and popunders the professional way. You will never see popups anymore. Permissions Visit
    website&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha" target="_blank"&gt;13. Stylebot:&lt;/a&gt;&lt;/b&gt;&lt;br&gt;Change the appearance of websites instantly. Preview and install styles created by other users on stylebot.me&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://chrome.google.com/webstore/detail/tab-number/dnndfognablbihihgnilabcegjjkiekj" target="_blank"&gt;14. Tab Number:&lt;/a&gt;&lt;/b&gt;&lt;br&gt;Tab number show number on each tab. If you want to jump a particular tab, So you can jump around easily by pressing ALT + pagenum.&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://chrome.google.com/webstore/detail/thin-scroll-bar/ojmmnceaidnmminjjffpndcbdibelgam" target="_blank"&gt;15. Thin Scroll Bar:&lt;/a&gt;&lt;/b&gt;&lt;br&gt;Thin Scroll Bar to increase screen space for little more visibility.&lt;br&gt;&lt;br&gt;
&lt;/div&gt;</description><category>browser</category><guid>https://avilpage.com/2014/09/a-few-chrome-extensions-for-efficient.html</guid><pubDate>Mon, 08 Sep 2014 12:20:00 GMT</pubDate></item><item><title>Use Space As Both Space &amp; Control - Avoid Emacs Pinky!</title><link>https://avilpage.com/2014/08/use-space-as-both-space-control-avoid.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Most of the  commands  in  Emacs start with  'Control' &amp;amp; 'Meta'. Control key is present at the corners of the keyboard, and it's very uncomfortable to press it every-time to invoke a command. Most popular solution to this is to swap CAPS lock &amp;amp; CTRL key. But you have to press the key with Pinky which might cause Emacs Pinky.&lt;/p&gt;
&lt;p&gt;A much better solution is to use space bar as control key. When you press the space bar, it will function as a normal space key. If you press it with any other key. it will function as control key. So, to run any commands, you can hold space with one thumb and press other key(s) with another hand which will be handy.&lt;/p&gt;
&lt;p&gt;In Linux, we can achieve this with Space2Ctrl.&lt;/p&gt;
&lt;p&gt;Install the dependencies, clone the repo, make and start the script.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;libx11-dev&lt;span class="w"&gt; &lt;/span&gt;libxtst-dev

git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/r0adrunner/Space2Ctrl

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Space2Ctrl

make

./s2cctl&lt;span class="w"&gt; &lt;/span&gt;start
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can use your space as space and control key.&lt;/p&gt;
&lt;p&gt;If you are using Mac, you can use &lt;a href="https://pqrs.org/osx/karabiner/" target="_blank"&gt;Karabiner&lt;/a&gt; with the following modification.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Change spacebar to spacebar &amp;amp; control"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SpaceControl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;"manipulators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"spacebar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"modifiers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;"optional"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;"any"&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"right_control"&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;"to_if_alone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;"key_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"spacebar"&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"basic"&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>emacs</category><category>mac</category><category>ubuntu</category><guid>https://avilpage.com/2014/08/use-space-as-both-space-control-avoid.html</guid><pubDate>Fri, 29 Aug 2014 11:57:00 GMT</pubDate></item><item><title>Auto Remove Python Unused Imports &amp; Variables In Emacs</title><link>https://avilpage.com/2014/08/remove-unused-imports-variables-from.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;Unused code will distract you(and other people) while reading code.
Also, a single &lt;a href="http://stackoverflow.com/a/979069/2698552" target="_blank"&gt;unused import can cause out of memory
error&lt;/a&gt;. So,
it is considered as a bad practice. Lets try to get rid of unused
imports &amp;amp; variables from Python code.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/myint/autoflake" target="_blank"&gt;Autoflake&lt;/a&gt; removes
unused imports and unused variables as reported by pyflakes. Install it\&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--upgrade&lt;span class="w"&gt; &lt;/span&gt;autoflake
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now select a file which you want to clean and run this in terminal.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;autoflake&lt;span class="w"&gt; &lt;/span&gt;--in-place&lt;span class="w"&gt; &lt;/span&gt;--remove-unused-variables&lt;span class="w"&gt; &lt;/span&gt;example.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It removes all unused imports &amp;amp; variables from the file.&lt;/p&gt;
&lt;p&gt;Instead of running this command every time, I wrote a simple elisp
function and assigned a F8 key to that function. So while writing the
code itself it can clean it &amp;amp; it's much efficient.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;;; Py-rm - Remove unused variables &amp;amp; imports from python&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pyrm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;setq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;concatenate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"autoflake --in-place --remove-unused-variables "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;buffer-file-name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;shell-command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;; Reload the modified file&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;revert-buffer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;;; set a custom key for pyrm&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-set-key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;f8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'pyrm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Put the above code in your emacs configuration file, restart it &amp;amp; press
F8 whenever you want to clean the code.&lt;/p&gt;
&lt;p&gt;However, if you just need to highlight but not delete them, you can
install &lt;a href="http://flymake.sourceforge.net/" target="_blank"&gt;flymake&lt;/a&gt; and
then enter this.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;M-x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;flymake-mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;RET&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It just highlights the other syntax errors and unused imports but won\'t
delete them.&lt;/p&gt;
&lt;h4&gt;Screenshots&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Simple Python Code&lt;/strong&gt;&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/emacs-python-autoflake-1.png"&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unused code highlighted with flymake-mode&lt;/strong&gt;&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/emacs-python-autoflake-2.png"&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cleaned with autoflake&lt;/strong&gt;&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="https://avilpage.com/images/emacs-python-autoflake-3.png"&gt;
&lt;/p&gt;</description><category>emacs</category><category>python</category><guid>https://avilpage.com/2014/08/remove-unused-imports-variables-from.html</guid><pubDate>Sat, 16 Aug 2014 10:44:00 GMT</pubDate></item><item><title>Amazing Things To Do With Python In Everyday Life!</title><link>https://avilpage.com/2014/08/amazing-things-to-do-with-python-in.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;In Python, with a couple of imports and a few lines of code, we can do amazing things.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-swu9csx9zLM/U-0a5lWwZtI/AAAAAAAAKu0/DKagGQI3xhI/s1600/amazing-things-to-do-with-python.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-swu9csx9zLM/U-0a5lWwZtI/AAAAAAAAKu0/DKagGQI3xhI/s1600/amazing-things-to-do-with-python.jpg"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;I am post here a list of amazing scripts/projects that I came across.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://github.com/theGreatHeisenberg/VLC-With-Subtitles" target="_blank"&gt;VLC With Subtitles&lt;/a&gt;:  &lt;/b&gt;Automatically download and load correct subtitles in VLC.&lt;br&gt;&lt;br&gt;&lt;a href="https://github.com/rg3/youtube-dl" target="_blank"&gt;&lt;b&gt;Youtube-dl&lt;/b&gt;&lt;/a&gt;: Small command-line program to download videos from YouTube.com and other sites.&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://github.com/tito/2048" target="_blank"&gt;2048&lt;/a&gt;: &lt;/b&gt;2048 Game with Kivy(Also available on &lt;a href="https://play.google.com/store/apps/details?id=com.meltingrocks.kivy2048" target="_blank"&gt;Play Store&lt;/a&gt;, &lt;a href="https://itunes.apple.com/us/app/2048-with-kivy/id841404915?mt=8" target="_blank"&gt;iTunes&lt;/a&gt;, and for &lt;a href="https://github.com/bfontaine/term2048" target="_blank"&gt;terminal&lt;/a&gt;)&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;a href="https://github.com/DTVD/rainbowstream" target="_blank"&gt;&lt;br class="Apple-interchange-newline"&gt;Rainbowstream&lt;/a&gt;: &lt;/b&gt;A smart and nice Twitter client on terminal wrote by Python. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;a href="http://www.quora.com/Python-programming-language-1/What-are-the-best-Python-scripts-youve-ever-written/answer/Akshit-Khurana" target="_blank"&gt;Send Personal Messages&lt;/a&gt;&lt;/b&gt;:  Thank all your friends who wished on your birthday on Facebook.&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="http://www.avilpage.com/2014/06/t-minimal-to-do-list-for-geeks.html" target="_blank"&gt;T&lt;/a&gt;: &lt;/b&gt; A command-line todo list manager for people that want to finish tasks, not organize them.&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;b&gt;&lt;a href="https://www.youtube.com/embed/7rgph8en0Jc" target="_blank"&gt;qblog&lt;/a&gt;&lt;/b&gt;: Build &amp;amp; test a blog with Django 1.7 in less than 17 minutes.&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;a href="https://github.com/coursera-dl/coursera" target="_blank"&gt;couresera&lt;/a&gt;: &lt;/b&gt;Script for downloading Coursera.org videos and naming them.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;b&gt;&lt;a href="https://github.com/amoffat/sh" target="_blank"&gt;sh&lt;/a&gt;&lt;/b&gt;: Call any shell program as if it were a function.&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://github.com/myint/autoflake" target="_blank"&gt;AutoFlake&lt;/a&gt;: &lt;/b&gt;Remove unused imports and unused variables as reported by pyflakes.&lt;br&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;b&gt;&lt;a href="https://github.com/django-extensions/django-extensions" target="_blank"&gt;Django-Extensions&lt;/a&gt;: &lt;/b&gt;Collection of global custom management extensions for the Django Framework.&lt;br&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;b&gt;&lt;a href="https://github.com/clips/pattern" target="_blank"&gt;Pattern&lt;/a&gt;: &lt;/b&gt;Scrape &amp;amp; Process Web easily.&lt;br&gt;&lt;br&gt;&lt;a href="https://github.com/euske/pdfminer" target="_blank"&gt;&lt;b&gt;PDFMiner&lt;/b&gt;&lt;/a&gt;:  Exact a part(or entire) of text from pdf.&lt;br&gt;    &lt;b&gt; &lt;/b&gt;&lt;br&gt;&lt;b&gt;&lt;a href="https://github.com/noamraph/tqdm" target="_blank"&gt;tqdm&lt;/a&gt;: &lt;/b&gt;Add a progress meter to your loops in a second&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;b&gt;&lt;a href="https://github.com/micahflee/onionshare" target="_blank"&gt;onionshare&lt;/a&gt;: &lt;/b&gt;Securely and anonymously share a file of any size. &lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;&lt;a href="https://github.com/harelba/q" target="_blank"&gt;q&lt;/a&gt;:&lt;/b&gt; - Run SQL directly on CSV or TSV files.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://ipython.org/notebook.html" style="font-weight: bold;" target="_blank"&gt;iPython Notebook&lt;/a&gt;: Combine code execution, text, mathematics, plots and rich media into a single web document &amp;amp; share with others.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>python</category><guid>https://avilpage.com/2014/08/amazing-things-to-do-with-python-in.html</guid><pubDate>Fri, 15 Aug 2014 05:54:00 GMT</pubDate></item><item><title>How To Get Telugu Books If You Are Out Of Andhra!</title><link>https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;If you are a (Telugu) bookworm, and you are living out of Andhra, then getting Telugu books is a huge problem. Thankfully a lot of online stores are coming forward to solve this problem. Let's look at a few sites where we can get Telugu print &amp;amp; e-books.  &lt;/p&gt;
&lt;h4&gt;1. Digital Library of India&lt;sup id="fnref:dli"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fn:dli"&gt;1&lt;/a&gt;&lt;/sup&gt;: [Free]&lt;/h4&gt;
&lt;p&gt;Government of India is spending a crazy amounts of money to digitize public domain books. This is the best place to get telugu ebooks for free of cost. Currently there are 23,370 books in Telugu. Eventhough you won't new books there, you can find a lot of great classics.&lt;/p&gt;
&lt;h4&gt;2. Kinige&lt;sup id="fnref:kinige"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fn:kinige"&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/h4&gt;
&lt;p&gt;This is the most popular site(Alexa Traffic Rank: 118,798) for buying Telugu books online. They supply both print books &amp;amp; e-books. The good thing about Kinige is they rent the for a period of 30 days at a reduced price. Most books are available here and is a good place to get started.&lt;/p&gt;
&lt;h4&gt;3. Logili&lt;sup id="fnref:logili"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fn:logili"&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/h4&gt;
&lt;p&gt;One more popular (Alexa Traffic Rank: 138,459) website to buy books online. It's also has great collection. However they sell only print books but no e-books. At times when there are no print books on Kinige, this is a great alternative.&lt;/p&gt;
&lt;h4&gt;4. Flipkart&lt;sup id="fnref:flipkart"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fn:flipkart"&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;/h4&gt;
&lt;p&gt;Most of you heard of Flipkart. You can't get all telugu books here but a few. If you are a regular shopper at flipkart, you might get available books at discount price.&lt;/p&gt;
&lt;h4&gt;5. Amazon&lt;sup id="fnref:amazon"&gt;&lt;a class="footnote-ref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fn:amazon"&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/h4&gt;
&lt;p&gt;It is struggling &amp;amp; competing with other online stores in India. Here also you can find a reasonable number of telugu books are great discounts.&lt;/p&gt;
&lt;p&gt;You can also buy telugu books at &lt;a href="http://www.supatha.in/index.php/"&gt;Supatha&lt;/a&gt;, &lt;a href="http://www.booksforyou.co.in/Language/Telugu"&gt;BooksForYou&lt;/a&gt;, &lt;a href="http://www.infibeam.com/Books/telugu-books-showcase.html"&gt;InfiBeam&lt;/a&gt;, &lt;a href="http://www.eveninghour.com/telugubooks.php"&gt;EveningHour&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In addition to these sites, authors or publication houses might be running their own sites ( for example &lt;a href="http://www.yandamoori.com/"&gt;Yandamoori&lt;/a&gt; sells his books from his site also ), you can buy from them also.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="http://www.avkf.org/"&gt;AVKF:&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Recently I came across AVKF. It also has a great collection of telugu books.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:dli"&gt;
&lt;p&gt;&lt;a href="http://www.dli.gov.in/"&gt;http://www.dli.gov.in/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fnref:dli" title="Jump back to footnote 1 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:kinige"&gt;
&lt;p&gt;&lt;a href="https://kinige.com"&gt;https://kinige.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fnref:kinige" title="Jump back to footnote 2 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:logili"&gt;
&lt;p&gt;&lt;a href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html"&gt;http://www.logili.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fnref:logili" title="Jump back to footnote 3 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:flipkart"&gt;
&lt;p&gt;&lt;a href="http://www.flipkart.com"&gt;http://www.flipkart.com&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fnref:flipkart" title="Jump back to footnote 4 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:amazon"&gt;
&lt;p&gt;&lt;a href="http://www.amazon.in"&gt;http://www.amazon.in&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fnref:amazon" title="Jump back to footnote 5 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:avkf"&gt;
&lt;p&gt;&lt;a href="http://www.avkf.org/"&gt;http://www.avkf.org/&lt;/a&gt; &lt;a class="footnote-backref" href="https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html#fnref:avkf" title="Jump back to footnote 6 in the text"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>telugu</category><guid>https://avilpage.com/2014/08/how-to-get-telugu-books-if-you-are-out.html</guid><pubDate>Wed, 13 Aug 2014 13:05:00 GMT</pubDate></item><item><title>How To Fix Washedout Colors In VLC Media Player?</title><link>https://avilpage.com/2014/08/fixing-colors-issues-in-vlc-media.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    Have you ever played a video on VLC or any other media player and seen this type of washed out colors or distorted video like these??&lt;br&gt;
    &lt;br&gt;

    &lt;div class="separator" style="clear: both; text-align: center;"&gt;
      &lt;a href="http://1.bp.blogspot.com/-7LVENit2IHs/U-oh1-k00iI/AAAAAAAAKt4/0R4JnnlFjUY/s1600/ubuntu-video-color-distortion.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-7LVENit2IHs/U-oh1-k00iI/AAAAAAAAKt4/0R4JnnlFjUY/s1600/ubuntu-video-color-distortion.png" height="358" width="640"&gt;&lt;/a&gt;
    &lt;/div&gt;&lt;br&gt;

    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br&gt;

    &lt;div class="separator" style="clear: both; text-align: center;"&gt;
      &lt;a href="http://4.bp.blogspot.com/--b5nPlhNGZE/U-oh3aIIHoI/AAAAAAAAKuI/WYmBdRWAJ0Q/s1600/vlc-ubuntu-troubleshooting.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/--b5nPlhNGZE/U-oh3aIIHoI/AAAAAAAAKuI/WYmBdRWAJ0Q/s1600/vlc-ubuntu-troubleshooting.png" height="358" width="640"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div style="text-align: center;"&gt;
      &lt;br&gt;
    &lt;/div&gt;To get rid of this problem, just open preferences from the Tools menu. Uncheck "Accelerated video output" from the video settings.&lt;br&gt;
    &lt;br&gt;

    &lt;div style="text-align: center;"&gt;
      &lt;a href="http://2.bp.blogspot.com/-EPdXHFnNZz4/U-ohzrxVXmI/AAAAAAAAKto/HH6mGnwDB8k/s1600/colors-washed-out-ubuntu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-EPdXHFnNZz4/U-ohzrxVXmI/AAAAAAAAKto/HH6mGnwDB8k/s1600/colors-washed-out-ubuntu.png" height="267" width="400"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div style="text-align: center;"&gt;
      &lt;br&gt;
    &lt;/div&gt;

    &lt;div style="text-align: center;"&gt;
      &lt;a href="http://3.bp.blogspot.com/-lDHjMz0mu0U/U-ohzWAi1WI/AAAAAAAAKtk/iXSAL3DGlaM/s1600/colors-distorted-ubuntu-vlc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-lDHjMz0mu0U/U-ohzWAi1WI/AAAAAAAAKtk/iXSAL3DGlaM/s1600/colors-distorted-ubuntu-vlc.png" height="285" width="400"&gt;&lt;/a&gt;
    &lt;/div&gt;&lt;br&gt;

    &lt;div style="text-align: center;"&gt;
      &lt;span style="text-align: left;"&gt; If you are using and old version of VLC, you might have an option to "Skip frames", you can select that option.
      Save your preferences and restart the VLC player. Now you can enjoy your videos. If the problem still persists make sure you have installed all your
      video drivers.&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style="text-align: center;"&gt;&lt;/div&gt;

    &lt;div style="text-align: center;"&gt;
      &lt;br&gt;
    &lt;/div&gt;

    &lt;div class="separator" style="clear: both; text-align: center;"&gt;
      &lt;a href="http://3.bp.blogspot.com/-A223-ZON4po/U-oh1D7OwJI/AAAAAAAAKt0/MVXZdBCLQ2Q/s1600/troubleshoot-vlc-ubuntu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-A223-ZON4po/U-oh1D7OwJI/AAAAAAAAKt0/MVXZdBCLQ2Q/s1600/troubleshoot-vlc-ubuntu.png" height="360" width="640"&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div class="separator" style="clear: both; text-align: center;"&gt;
      &lt;br&gt;
    &lt;/div&gt;

    &lt;div class="separator" style="clear: both; text-align: center;"&gt;
      &lt;br&gt;
    &lt;/div&gt;

    &lt;div class="separator" style="-webkit-text-stroke-width: 0px; clear: both; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; orphans: auto; text-align: center; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"&gt;
    &lt;/div&gt;
  &lt;/div&gt;</description><category>how-to</category><category>vlc</category><guid>https://avilpage.com/2014/08/fixing-colors-issues-in-vlc-media.html</guid><pubDate>Tue, 12 Aug 2014 08:57:00 GMT</pubDate></item><item><title>Django Meetup In Bangalore</title><link>https://avilpage.com/2014/06/magnificent-meetup-for-bangalore-django.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;i&gt;"Krace played a key role in bringing back the almost dead Bangalore Python Users Group into action."&lt;/i&gt;&lt;br&gt;&lt;i&gt;- Shreyansh Singhal on YourStory.&lt;/i&gt;&lt;br&gt;&lt;i&gt;&lt;br&gt;&lt;/i&gt;&lt;br&gt;&lt;i&gt;&lt;br&gt;&lt;/i&gt;&lt;span style="font-family: inherit;"&gt;Few weeks back, while I was searching for Python I came across &lt;a href="http://kracekumar.com/" target="_blank"&gt;Krace's blog&lt;/a&gt;. Then I checked his Github, Stackoverflow, Quora profiles and I was amazed.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Last week when I found there was a Django users workshop by him &amp;amp; his friends, without a second thought I decided to go.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Since the &lt;/span&gt;organizers&lt;span style="font-family: inherit;"&gt; marked the location (ThoughtWorks Technologies) on Google Maps, its quite easy to reach there w/o any trouble.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Workshop took place from 10 A.M. to 5 P.M. The goal was to build a &lt;a href="https://github.com/kracekumar/contactup" target="_blank"&gt;simple phone book app&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt; to add/view/edit contacts with Django &amp;amp; SQLite.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Before starting of workshop, organizers helped with installation of requirements(Django &amp;amp; South).&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Krace showed the agenda. At each &amp;amp; every step, he first explained what he is going to do. Then he would do it and gives us time to complete the task. All organizers patiently helped in troubleshooting the errors at each and every step. &lt;/span&gt;&lt;span style="font-family: inherit;"&gt;In the end we had little Q &amp;amp; A session.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Overall it was a great hands on experience with great content &amp;amp; crew! &lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Looking forward for more meetups!! &lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Thank You very much!!!&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;If you are form Bangalore &amp;amp; love Python, don't miss &lt;a href="http://www.meetup.com/Bangalore-Django-User-Group/" target="_blank"&gt;Django&lt;/a&gt; &amp;amp; &lt;a href="http://www.meetup.com/BangPypers/" target="_blank"&gt;BangPypers&lt;/a&gt; meetup.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;P.S: A snap of workshop.. &lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-UDPwtjlSiKc/U5QJzUGjxMI/AAAAAAAAKkM/oG2iPbokc68/s1600/django-workshop.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-UDPwtjlSiKc/U5QJzUGjxMI/AAAAAAAAKkM/oG2iPbokc68/s1600/django-workshop.jpeg"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;br&gt;&lt;/div&gt;</description><category>bangalore</category><category>django</category><category>meetup</category><guid>https://avilpage.com/2014/06/magnificent-meetup-for-bangalore-django.html</guid><pubDate>Sun, 08 Jun 2014 01:46:00 GMT</pubDate></item><item><title>A Weather Widget For Your Terminal!</title><link>https://avilpage.com/2014/06/a-weather-widget-on-your-terminal.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Getting weather info right on the terminal..?? Sounds cool.. Isn't it? With Python, it's even easier to make one! Lets get started.&lt;br&gt;&lt;br&gt;First we need to determine the location of the user. So let's find out ip address. There are a lot of sites which gives the ip address but &lt;a href="http://checkip.dyndns.org/" target="_blank"&gt;this site&lt;/a&gt; is the simplest &amp;amp; very easy to get.&lt;br&gt;&lt;br&gt;Once we have the ip address, we can use it to determine the location and then use any weather api to get the info. However &lt;a href="http://worldweatheronline.com/" target="_blank"&gt;Worldweatheronline&lt;/a&gt; api gives weather info directly based on the api, which makes it easier to fetch data.&lt;br&gt;&lt;br&gt;We can get the data in JSON format and by parsing it we can make the weather widget.&lt;br&gt;&lt;br&gt;I wrote a &lt;a href="https://github.com/ChillarAnand/Weather-on-Terminal" target="_blank"&gt;simple script&lt;/a&gt; for that and here is the sample output of the script.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-_b09ZZBmFHk/U48GvsG0wPI/AAAAAAAAKj8/LU7WmtkKO_o/s1600/weather-widget-terminal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-_b09ZZBmFHk/U48GvsG0wPI/AAAAAAAAKj8/LU7WmtkKO_o/s1600/weather-widget-terminal.png"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;  &lt;/div&gt;&lt;/div&gt;</description><category>command-line</category><category>python</category><guid>https://avilpage.com/2014/06/a-weather-widget-on-your-terminal.html</guid><pubDate>Wed, 04 Jun 2014 06:16:00 GMT</pubDate></item><item><title>Definition Of Infatuation From 100% Love Telugu Movie!</title><link>https://avilpage.com/2014/05/definition-of-infatuation-from-100-love.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;According to Freud psychology, Infatuation is only an attraction between male and female and it's a state of being completely carried away by unreasoned passion foolish examined feeling and unappreciated often completely unwarranted emotion.&lt;/div&gt;</description><category>telugu</category><guid>https://avilpage.com/2014/05/definition-of-infatuation-from-100-love.html</guid><pubDate>Mon, 12 May 2014 08:14:00 GMT</pubDate></item><item><title>The Mysterious Wall - Best Zen Story By Osho!</title><link>https://avilpage.com/2014/05/the-mysterious-wall-best-zen-story-by-osho.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-family: inherit;"&gt;Osho is a great story teller. Whether he is writing a book, preaching his students, giving speeches, he tells interesting short stories. I have read a lot of them from his books. This is one of my favorite stories.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;Osho I used present tense above because Osho believes that he is '&lt;/span&gt;&lt;quote&gt;Never Born, Never Died. Only Visited this Planet Earth.'&lt;/quote&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;&lt;span style="font-family: inherit;"&gt;The Mysterious Wall!&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;There was an ancient mysterious wall which stood at the edge of a village, and whenever anyone climbed the wall to look onto the other side, instead of coming back he or she smiled and would jump to the other side, never to return. &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;The inhabitants of the village became curious as to what could draw these people to the other side of the wall. After all, their village had all the necessities of living a comfortable life.They made an arrangement to where they would tie a person's feet, so that when he or she looked over and wished to jump, they could be pulled back.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;The next time someone tried to climb the wall to see what was on the other side, they chained her feet so that she could not go over. She looked on the other side and was delighted at what she saw, and smiled.Those standing below grew curious to question her and pulled her back, but to their great disappointment she had lost the power of speech.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;i&gt;"Those who have Seen cannot say. That which has been Seen cannot be painted, cannot bereduced to words. But still each one has to give a try - and the world goes on becoming more and more beautiful because of these efforts."&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</description><category>zen-stories</category><guid>https://avilpage.com/2014/05/the-mysterious-wall-best-zen-story-by-osho.html</guid><pubDate>Thu, 08 May 2014 21:43:00 GMT</pubDate></item><item><title>Split/Merge PDF Files From Command Line</title><link>https://avilpage.com/2014/05/split-merge-stitch-pdf-file-ubuntu.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Sometimes we come across a situation where we need to split or stitch the pdf document. The simplest and easiest way is to use PDF Toolkit on the command line.&lt;/p&gt;
&lt;p&gt;Let's first install it using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;pdftk
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that pdftk is installed, lets take a smaple pdf file and split it into parts.&lt;/p&gt;
&lt;h4&gt;Splitting PDF&lt;/h4&gt;
&lt;p&gt;We can split the entire pdf into single pages using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pdftk&lt;span class="w"&gt; &lt;/span&gt;myFile.pdf&lt;span class="w"&gt; &lt;/span&gt;burst
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can also split only specific page by specifying the page number:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pdftk&lt;span class="w"&gt; &lt;/span&gt;myFile.pdf&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;page_21.pdf
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also split specific set of pages by using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pdftk&lt;span class="w"&gt; &lt;/span&gt;myFile.pdf&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;21&lt;/span&gt;-end&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;21_to_last.pdf
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Merging PDF&lt;/h4&gt;
&lt;p&gt;Now that we have scissored a lot of pages. Let's go ahead and stitch a few of them.&lt;/p&gt;
&lt;p&gt;We can merge specific pages by using the following command:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pdftk&lt;span class="w"&gt; &lt;/span&gt;page_21.pdf&lt;span class="w"&gt; &lt;/span&gt;21_to_end.pdf&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;stitched.pdf
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will stitch the two pdf's we created above.&lt;/p&gt;
&lt;p&gt;If we have a huge list of single age pdf's in a folder and if we want to stitch them together, we can run the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;pdftk&lt;span class="w"&gt; &lt;/span&gt;*.pdf&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;output&lt;span class="w"&gt; &lt;/span&gt;newFile.pdf
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will stitch all the pdf in the current directory to a single pdf.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;That's it. We have successfully split and merged pdf files using pdftk. Hope you find this useful.&lt;/p&gt;</description><category>command-line</category><category>linux</category><guid>https://avilpage.com/2014/05/split-merge-stitch-pdf-file-ubuntu.html</guid><pubDate>Wed, 07 May 2014 08:14:00 GMT</pubDate></item><item><title>How To Use Python &amp; Beautiful Soup To Scrap Web Pages On Ubuntu</title><link>https://avilpage.com/2014/04/how-to-use-python-beautiful-soup-to.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-family: inherit;"&gt;In this tutorial, You will learn to install Beautiful Soup and parse any web page you like.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;h2 style="text-align: left;"&gt;&lt;span style="font-family: inherit;"&gt;Python &amp;amp; Beautiful Soup Installation On Ubuntu 12.04:&lt;/span&gt; &lt;/h2&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;1. Open your terminal ( Alt + Ctrl + T ). Install Python &amp;amp; Soup by using these commands.&lt;/span&gt;&lt;/div&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span style="color: #eeeeee;"&gt;&lt;div&gt;&lt;br&gt;sudo add-apt-repository ppa:fkrull/deadsnakes&lt;br&gt;&lt;br&gt;sudo apt-get update&lt;br&gt;&lt;br&gt;sudo apt-get install python2.7 &lt;br&gt;&lt;br&gt;sudo apt-get install python-bs4&lt;/div&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;&lt;span style="font-family: inherit;"&gt;Scraping A Web Page: &lt;/span&gt;&lt;/h2&gt;&lt;span style="font-family: inherit;"&gt;Lets start our programm by importing Beautiful soup. Since we are going to open a web page, we need urllib2 ( This is for Python 2, For Python 3 see urllib.request ). So import that library also.&lt;code&gt;&lt;span style="color: #eeeeee;"&gt; &lt;/span&gt;&lt;/code&gt;Select any url to parse. I have selected the home page of this blog and opened that page with urlopen().&lt;code&gt;&lt;span style="color: #eeeeee;"&gt; &lt;/span&gt;&lt;/code&gt;Pass the web page contents of 'page' variable to beautiful soup.&lt;code&gt;&lt;span style="color: #eeeeee;"&gt; &lt;/span&gt;&lt;/code&gt;Lets print all the links which are present in this page.&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;So, the final code is&lt;/span&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span style="color: #eeeeee;"&gt;&lt;div&gt;&lt;br&gt;from bs4 import BeautifulSoup&lt;br&gt;import urllib2&lt;br&gt; &lt;br&gt;url = "https://www.goodreads.com/quotes/tag/love"&lt;br&gt;page = urllib2.urlopen(url)&lt;br&gt;soup = BeautifulSoup(page.read())&lt;br&gt; &lt;br&gt;for anchor in soup.find_all('a'):&lt;br&gt;    print(anchor.get('href', '/')) &lt;/div&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;span style="font-family: inherit;"&gt;Go ahead and run this file. I have name the file as scrap_web_page.py&lt;/span&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span style="color: #eeeeee;"&gt;&lt;div&gt;&lt;br&gt;python scrap_web_page.py&lt;/div&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;It will produce all the links in the terminal itself. I have added a screenshot of the output I have received.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-QoTo6Nmu8IA/U16noONHUII/AAAAAAAAKas/uNAm2sooDO8/s1600/python-beautiful-soup-how-to.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-QoTo6Nmu8IA/U16noONHUII/AAAAAAAAKas/uNAm2sooDO8/s1600/python-beautiful-soup-how-to.png" height="277" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;anchor.get() is just one method to get all links, you can grab any element or class or name or anything from the page. For complete details, read the &lt;a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/" target="_blank"&gt;documentation of Beautiful Soup&lt;/a&gt;. &lt;/span&gt;&lt;/div&gt;</description><category>python</category><category>scraping</category><category>ubuntu</category><guid>https://avilpage.com/2014/04/how-to-use-python-beautiful-soup-to.html</guid><pubDate>Mon, 28 Apr 2014 13:43:00 GMT</pubDate></item><item><title>Custom Key Maps For Vimium To Speed Up Browsing</title><link>https://avilpage.com/2014/04/useful-custom-key-maps-for-vimium-to.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
            &lt;span style="text-align: left;"&gt;For keyboard ninjas, Vimium is a boon! Vimium made browsing with keyboard a cat walk and ditch the mouse completely! This
                post is specifically written for those who are good at &lt;a href="http://www.vim.org/" target="_blank"&gt;Vim&lt;/a&gt; and installed &lt;a href="https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en" target="_blank"&gt;Vimium on Chrome&lt;/a&gt; or &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/vimium/" target="_blank"&gt;Firefox&lt;/a&gt;!&lt;/span&gt;&lt;br&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                Vimium is THE BEST Chrome extension for Keyboard navigation! Since it was inspired by Vim, most of the shortcuts resemble that of vim. In Vim, we can set
                custom maps, if we are not comfortable with a particular command. The same goes for Vimium also!
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                By having some custom mapping, we can make surfing the web much easier and productive! Lets look at some custom maps which will come handy in everyday
                browsing.
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;h3 style="clear: both; text-align: left;"&gt;0. Characters Used for Link Hints!&lt;/h3&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                By default some characters are set for link hints. But I am more comfortable with the following keys
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                "sdfercvjkluim". So I set the characters to "fjdkslrueiwvm". But You can choose the key which you are comfortable with and use them. So when you press
                "f" or "F", characters used to suggest links will be the ones which you are comfortable to type!
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;h3 style="clear: both; text-align: left;"&gt;1. Navigating Your History!&lt;/h3&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                I navigate back and forth a lot. To back in history, I need to press "H" ( which means SHIFT + h ). So I mapped this 'h'. Actually by default h is
                mapped to scroll left, which I never use at all. So, to go back 3 pages in history, U just press "3h". The same applies for "L" also.
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;h3 style="clear: both; text-align: left;"&gt;2. Navigating to New pages&lt;/h3&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                By default "o" is mapped to open URL ( or bookmarks or history ) in current tab and "O" to open them in new tab. Most of the time, I need to open URL in
                new tabs only so I swapped the above options. The same goes for "b" ( for bookmarks ) also.
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                You can get a list of all shortcuts  at &lt;a href="https://github.com/philc/vimium#keyboard-bindings" target="_blank"&gt;Vimium Github page&lt;/a&gt; or if You
                have installed Vimium, You can just press "?" You can set these custom maps in advanced settings of Vimium 
            &lt;/div&gt;

            &lt;div class="separator" style="clear: both; text-align: left;"&gt;
                &lt;br&gt;
            &lt;/div&gt;

            &lt;h4 style="clear: both; text-align: left;"&gt;Custom Key Mappings&lt;/h4&gt;

            &lt;div&gt;
                &lt;div dir="ltr" trbidi="on"&gt;
                    &lt;code class="bash hljs" style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;
                        &lt;span style="color: #eeeeee;"&gt;&lt;br&gt;
                            map h goBack&lt;br&gt;
                            map l goForward&lt;br&gt;
                            map o Vomnibar.activateInNewTab&lt;br&gt;
                            map O Vomnibar.activate&lt;br&gt;
                            map b Vomnibar.activateBookmarksInNewTab&lt;br&gt;
                            map B Vomnibar.activateBookmarks&lt;/span&gt;
                    &lt;/code&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;p&gt;
            Characters used for Link hints:
        &lt;/p&gt;

        &lt;div dir="ltr" trbidi="on"&gt;
                            &lt;code class="bash hljs" style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span style="color: #eeeeee;"&gt;fjdkslrueiwvm&lt;/span&gt;
                &lt;/code&gt;
            
        &lt;/div&gt;

        With these custom key maps, browsing becomes much productive.</description><category>browser</category><guid>https://avilpage.com/2014/04/useful-custom-key-maps-for-vimium-to.html</guid><pubDate>Sat, 26 Apr 2014 08:04:00 GMT</pubDate></item><item><title>Access Clipboard From Linux Terminal</title><link>https://avilpage.com/2014/04/access-clipboard-from-terminal-in.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;If You are going back and forth between terminal and any other application, accessing system clipboard contents from command line will be invaluable.&lt;br&gt;&lt;br&gt;If You are using mac, there are inbuilt commands pbcopy &amp;amp; pbpaste. But in Ubuntu these are not available. You need to install a small utility called xclip. Go ahead and install it.&lt;br&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; color: #eeeeee; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span class="hljs-built_in" style="box-sizing: border-box; color: #268bd2;"&gt;sudo&lt;/span&gt; apt-get install xclip&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;Now, You can copy any text ( or the output one command ) into the clipboard using xclip. To copy contents of fruits.txt to clipboard,&lt;br&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; color: #eeeeee; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;cat fruits.txt | xclip&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;If You want to see the contents of clipboard, You can use&lt;br&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; color: #eeeeee; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;xclip -o&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;This copy and paste will work only in the terminal, If You switch to another application and try to paste there, it wont work.&lt;br&gt;&lt;br&gt;If You want to paste in another application, You need to copy like this&lt;br&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; color: #eeeeee; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;cat fruits.txt | xclip -selection clipboard&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;Now, You can switch to any other application &amp;amp; You can paste (CTRL + V) the contents.&lt;br&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;Tip:&lt;/h2&gt;Instead of typing all of this everytime, You can setup alias in .bashrc file&lt;br&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span style="color: #eeeeee;"&gt;alias c='xclip -selection clipboard'&lt;br&gt;alias v='xclip -o'&lt;/span&gt;&lt;span style="color: #eeeeee;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Now You can easily copy the contents like this&lt;br&gt;&lt;br&gt;&lt;div dir="ltr" trbidi="on"&gt;&lt;div style="text-align: center;"&gt;&lt;pre style="box-sizing: border-box;"&gt;&lt;code class="bash hljs " style="background-color: #333333; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 10px inset, rgba(255, 255, 255, 0.0980392) 0px 1px 0px, rgba(0, 0, 0, 0.498039) 0px -1px 0px; box-sizing: border-box; display: block; padding: 15px 20px; position: relative; text-align: left;"&gt;&lt;span style="color: #eeeeee;"&gt;cat fruits.txt | c&lt;/span&gt;&lt;/code&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;I found this a lot helpful while switching between browser and terminal.&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>command-line</category><category>linux</category><guid>https://avilpage.com/2014/04/access-clipboard-from-terminal-in.html</guid><pubDate>Sun, 20 Apr 2014 14:01:00 GMT</pubDate></item><item><title>చలం వ్యాసాలు - ఆనందం (Aanandam - Gudipati VenkataChalam )</title><link>https://avilpage.com/2014/04/aanandam-essay-by-gudipati-venkatachalam.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;లోకం ఆనంద మయం. ఆనందం కోసమే ప్రయత్నిస్తుంది. ప్రతి జీవి యొక్క పరమావధి ఆనందమే... పశువులు పక్షులు అన్నిటికి బాధ నుంచి తప్పించుకోవాలని హాయి గా బతకాలని ఒక్కటే ప్రయత్నం. మనుష్యులు హాయి గా బతకటమే కాకుండా కొన్ని విధాలైన ఆనందాన్ని కూడా పొందాలని చూస్తారు. బాధ కావాలని కోరే వారెవరు లేరు. కోరి బాధ లు పడే వాళ్ళూ, సుఖాన్ని త్యజించే వాళ్ళూ లేక పోలేదు. చచ్చిన వాళ్ళను మర్చిపోక వూరికే జ్ఞాపకం చేసుకుని ఏడ్చే వాళ్ళూ , ఇతరుల సౌఖ్యం కోసం తమ ఆనందాన్ని వొదులుకునే వాళ్ళూ, నోట్లోంచి కడ్డీలు దూర్చుకునే వాళ్ళూ , పంచాగ్ను ల మద్య తపస్సు చేసే వాళ్ళూ వున్నారు. కాని , ఆ బాధ వాళ్లకు ఆనందం కనుక లేక ఆనందకరమైనది బాధ వల్ల సమకూరుతుంది అనుకుంటారు కనుక , ఆ బాధ పడతారు.&lt;br&gt;&lt;br&gt;ఆనందం అనేక రకాలు. ముఖ్యం పంచేంద్రియాలవల్ల, సంపాయించేది. మనసు వల్ల పొందేది.. వున్నతమైన ఆలోచనలూ, సంభాషణా స్నేహమూ ప్రేమా మొదలైన వాటివల్లా సౌందర్యాల వల్ల కలిగే ఆనందం; అందమైన కధలూ, నాటకమూ, సంగీతమూ, బొమ్మలూ మొదలైన వాటివల్ల కలిగే ఆనందం. ఈ ఆనందం లోనే యెక్కువ తక్కువ లు వున్నాయి. తిని నిద్ర పోయి జంతువులవలే బతుకులో పొందే ఆనందం, గంతులేసి నవ్వి అల్లరి గా వుంటే వచ్చే ఆనందం, తృప్తి పడి నా కింకేమీ అక్కర్లేదని శాంతం గా వుండే ఆనందం, లోకమంతా తనకే కావాలనే అధికారాలకీ, ధనార్జనకీ కష్ట పడుతు పొందే ఆనందం, దేశాల్ని, సంఘాల్ని బాగు చెయ్యలనీ, కొత్త విజ్ఞానాన్ని సంపాయించాలని, కొత్త లోకాన్ని కనిపెట్టాలనీ ప్రయత్నిస్తో జీవితాలర్పించే ఆనందం.&lt;br&gt;&lt;br&gt;ఇవేకాక మనకు తెలీనివీ, ఈ భూలోకానికే చెందనివీ, ఇంకా మనం చూసే ఆకాశానికీ ఇతర గోళాలకు చెందినవీ అనేక విధాలైన ఆనందాలు వుండవచ్చు. చీమ పొందే ఆనందం వుంది మనం పొందే ఆనందం వుంది. భేదం ఇంద్రియ భేదం వలన కలుగుతోంది. దాని కళ్ళు మన కళ్ళు ఒకే కాంతిని చూడవు. చెవులు ఒకటే ధ్వని ని వినవు. అట్లానే మనకే ఇంకా బలమైన చెవులు - కళ్ళు వుంటే, ఆకాశ ధ్వనులు, కాంతులు, -- ఆకులు చేసే రహస్య గీతాలు -- కీటకాల సంభాషణ, -- ఎన్ని వినగలమో, చూడగలమో.&lt;br&gt;&lt;br&gt;అంతే కాదు ఈ పంచేంద్రియాలు వుండబట్టి ఈ ఆనందాన్ని అనుభవిస్తున్నాము. పది జ్ఞానేంద్రియాలుంటే - పది రకాలు ఈ ఐదూ కాక, ఇంకో విధమైనవి వుంటే - కొంచం ఆలోచిస్తే తెలుస్తుంది - అనంత మైన ఆనందాలు వుండటానికి వీలుందని. భూలోకం లో ఈ విధమైన ఆనందాలున్నాయి; చంద్ర లోకం లో, అనూరాధా లోకం లో, ఆరుద్ర లోకం లో -- చెప్పలేము&lt;br&gt;&lt;br&gt;ఇవన్ని శరీరాలకు సంభందించిన ఆనందాలు. మతాలు ఇంకో ఆనందాన్ని గురించి చెపుతాయి. ఆ ఆనందాన్ని స్వర్గ లోకం లో పొందుతామంటారు. ఆ ఆనందం రెండు విధాలు. భూలోకపు ఆనందాల వంటివే శరీరానికి సంభందించినవి, రెండోది ఈశ్వరుడి సాన్నిధ్యం వల్ల కానీ, స్తోత్రం వల్ల కాని, లేక ఐక్యం వల్ల కాని, కలిగే ఆనందమూ, ఆ స్వర్గానందాలకు భూఆనందాలకు విరోధం అంటారు. అవి కావాలంటే వీటిని త్యజించాలి. ముఖ్యం గా ఆ స్వర్గం సంగతి తెలిసిన వాళ్ళు కొన్ని నీతులను చట్టాలను ఏర్పరిచారు. ముఖ్యం గా వాటిని అతిక్రమించకుండా సంచరిస్తే ఆ స్వర్గము, ఈశ్వరుడు దొరుకుతారు. కాని , ఆ ప్రకారం చేస్తున్న మనుష్యులెవ్వరు కనబడరు. ఎవరికి అది నిశ్చయం లేదనుకుంటా. ఒకవేళ అందరు వివేక వంతులై ఆ స్వర్గం కోసం క్షణ భంగురమైన ఈ భూలోక ఆనందాలని త్యజించి ఆ శాస్త్ర ప్రకారం ఆ చట్టాలు, ఆ ధర్మాలు అనుష్టిస్తారు అనుకోండి, ఆ స్వర్గం ఏట్లా వున్నా ఈ భూలోకం ధ్వంసమైపోతుంది.&lt;br&gt;&lt;br&gt;ఇప్పుడున్న తమాషా, నవ్వు, ప్రేమా, స్నేహమూ అన్నీ నశించి ఈ లోకం నివాస యోగ్యం కాకుండా పోతుంది. ఎంత త్వరలో ఈ లోకాన్ని విడిచి ఆ లోకానికి వెళితే అంత వుత్తమం గా తోచాలి ఈ ప్రజలకు. మొత్తానికి ఎవరిని చూసినా ఈశ్వరుడు, ఆయన లోకమూ, దాని మార్గము గురించి మాట్లాడే వాళ్ళే కాని, ఈ లోకాన్ని విడిచి ఆ లోకానికి, దాని ఆనందాల కోసం త్వర గా ప్రయాణమవుతున్న వాళ్ళు ఎవ్వరు కనిపించరు.&lt;br&gt;&lt;br&gt;ప్రతి వాళ్ళు బాధ నుంచి తప్పించుకుని ఆనందాన్ని పొందుదామని చూస్తారుగాని ఆ నేర్పు కలిగి ఆనందాన్ని పొందగలిగే వాళ్ళు కొద్దిమందే కనపడతారు. మన "ఇన్ స్టింక్ట్" ఆనందం కోసం బలీయం గా వుంది. తనకు బాధ కలిగించే పనుల నుంచి మన శరీరం తనంతట తానే తప్పుకుంటుంది. కాని మన మనసుకు మాత్రం ఇంకా ఆ "ఇన్ స్టింక్ట్" రాలేదు. జ్ఞానము , నేర్పు ఇంకా సంపాయించలేదు. ఏది తమకు ఆనందం ఇస్తుందో, బాధల నుంచి ఎట్లా తప్పుకోగలరో మనుష్యులు ఇంకా నేర్చుకోలేదు, కనుకనే ఎవడు వచ్చి "ఆనందం" అని కేకలు వేసినా వాడి వెంట పరుగెత్తుతారు.&lt;br&gt;&lt;br&gt;ఆనందం విషయమై కొన్ని నిబంధనలు కనపడుతున్నాయి.&lt;br&gt;నాకు ఆనందం కావాలి, నేను ఆనందం అనుభవించాలి అని ప్రయత్నిస్తే వొచ్చేట్లు కనపడదు. ఒక కార్యం ద్వారానే కలుగుతుంది ఆనందం. మనసు ఆ కార్యం మీద వుండాలికాని ఆనందం మీద వుంటే ఆనందం చెదిరిపోతుంది. తీపి కావలన్న వాడూ తీపి కోసం ఎక్కడన్నా వెతుకుతుందా? తీపి నివ్వగల చెరుకు కోసం వెతకాలి. అట్లానే ఆనందం కావాలిస్తే ఒంటరిగా కూచుని ఎవరికి లేకుండా కొంత ఆనందంసంపాయించుకోవాలంటే అది క్షుద్రరూపాల ప్రసన్న మవుతుంది. ఒక్క నిమిషము లో నశిస్తుంది. మనం జీవిస్తున్నాం, మనకు ఆనందం కావాలి అనే ధ్యాస లేకుండా జీవితాన్ని గొప్ప వుద్యమాల్లో, లోక క్షేమానికి ప్రపంచానందానికి చేసే ఘన ప్రయత్నాలలో ఐక్యమయ్యే మనిషి పొందే ఆనందాన్ని స్వార్ధపరులు పొందనట్లు తోస్తుంది. మొదటి రకపు ఆనందం స్వభావమే వుత్తమమైనది గా తోస్తుంది.. ఒక ఆనందమైన కధనుగాని, బొమ్మను గాని సృష్టించే ఆనందం తలుచుకోండి...&lt;br&gt;&lt;br&gt;ఈ ఆనందం ఎవ్వరికి ఇవ్వను; నేనే దాచుకుంటాను అన్న నిమిషాన ఆ ఆనందం మాయ మౌతుంది . చెట్టునున్న పువ్వును జేబులో దాచుకున్నట్లు, ఎవరెత్తుకుపోతారో అని భార్యలను దాచుకునే వాళ్ళు, ఈ విషయమై కొంచం ఆలోచిస్తే బాగుంటుంది.... చక్క గా యోచిస్తే ఇతరులనుంచి దాచుకున్నామన్న తృప్తి తప్ప ఏ మాత్రమూ వాళ్ళు ఆనందాన్ని పొందలేరు.&lt;br&gt;&lt;br&gt;తనే ఆనందం పొందాలనే కార్యాలకన్నా ఇతరులకు ఆనందమిద్దామనే వూహ తో చేసే కార్యాలు ఎక్కువ ఆనందాన్ని ఇస్తాయి. తిండి తినటానికి సంగీతం పాడటానికి భేదం ఆలోచించండి. అందువల్లనే ప్రేమ వలన వచ్చే ఆనందం అద్వితీయమైనది. ఎందుకంటే ప్రేమ వున్నప్పుడు తనకి ఎంత ఆనందం వస్తుందనే ధ్యాస వుండదు. ఎంతసేపు ఇతరులకు ఎంత ఆనందం ఇవ్వగలమనే యోచనే బలం గా వుంటుంది..&lt;br&gt;&lt;br&gt;ప్రపంచమంతా ఆనందం పొంగి పొర్లి పోతోంది. దాన్ని అందుకోగలిగిన హృదయాలు వుండాలి. లోకం అంతా కాంతి వుంది. కాని కన్ను వుంటే కాని ఆ కాంతి అర్ధం కాదు. ఎంత శక్తి కలిగిన కన్ను వుంటే అంత కాంతి వుపయోగపడుతుంది. లోకమంతా శక్తి నిండి వుంది. ఆ శక్తి ని వుపయోగపరచుకునే యంత్రాన్ని బట్టి ఆ శక్తి వ్యక్తమవుతుంది. అట్లానే ఆనందం. ఆకాశం, సముద్రం, గాలి, ఇసిక, స్నేహం, తోటలు, నదులు,, కీటకాలు, పసిపిల్లలు, నవ్వు అన్నీ ఆనందమే. తెలుసుకునే హృదయం వుండాలి. ఆ హృదయానికి ఎంత శక్తి వుంటే అంత ఆనందాన్ని తీసుకోగలదు.&lt;br&gt;&lt;br&gt;వెన్నెల అందరికి కాస్తుంది. వెన్నెల రాకుండా కిటికీలు మూసుకునే వాళ్ళు వున్నారు. వెన్నెల చాలదని ఎలక్ట్రిక్ లైట్లు పెట్టుకునే వాళ్ళు వున్నారు. వెన్నెలలోని ఆనందాన్ని భరించలేక గీతాల్లోకి ఆ అనందాన్ని పొల్లేట్లు చేసే వాళ్ళు వున్నారు. ఆ ఆనందం అతీతమై వాళ్ళకే తెలియని పిచ్చి బాధ లో పడిపోయే ఆత్మ లూ వున్నాయి.&lt;br&gt;&lt;br&gt;ప్రతి జీవికి కొంత శక్తి వుంది. కొంత కాలం వుంది. ఈ శక్తినీ కాలాన్నీ ఆనందం లో కూర్చుకునే తెలివితేటలు లేవు. జీవితం "ఆర్ట్". ఒక కళ. మనం వివేకవంతులమైతే మన శక్తి నంతా ఆనందం గా మార్చుకోగలం. మన కాలమంతా మనకు ఆనందాన్ని ఇచ్చేట్లు చేయగలం. ఈ మహా శక్తి మన పుటకవల్లనో సంస్కారం వల్లనో కొంత కలుగుతుంది. కొంత మనకు చిన్నప్పుడు ఇతరులు నేర్పిన "అలవాట్ల" వల్లా పెద్దయ్యి మనకు మనమిచ్చుకునే శిక్షణ వల్లా యేర్పడుతుంది.&lt;br&gt;&lt;br&gt;లోకం లో మొత్తానికి ఎవరు ఆనందవంతులుగా కనపడుతున్నరంటే, వారి స్వభావాలకీ, గుణాలకి, వేటి వేటి మధ్య వున్నారో ఆ పరిస్తితులకు; సమత్వం కలిగించుకున్న వాళ్ళు.. చాపలు ఎంత మంచి మందిరాలలో వుంటే యేమి లాభం? ఏనుగులు సముద్రాల మధ్య తెల్లని ఇసుకల్లో పడుకుంటే ఏం సౌఖ్యం? తక్కువ స్థితిలో వున్నా, ఎక్కువ స్థితి లో వున్నా సరిపోవాలి. లోకానికి వ్యక్తి కి సంధి కుదరాలి. వ్యక్తి లోని శక్తులన్నీ చక్క గా వినియోగమయ్యే పరిస్తితి వుండాలి. చిత్రకారుణ్ణి చిత్రించ వద్దని ఆజ్ఞ పెట్టి మహారాజు గా చేసినా అతనికి తృప్తి వుండదు. తన కళ కోసం బాధ లోనే వుంటాడు.&lt;br&gt;&lt;br&gt;&lt;br&gt;లోకం లో అనేక విధాలైన ప్రాణాలున్నాయి. కంటి కగపడని సూక్ష్మ జీవుల నుంచి మనుష్యుల వరకు -- అనేక స్తితులలో అనేక ప్లేన్ ల లో బ్రతికేవి వున్నాయి. వేటి గుణాలు,ఆకారం,కష్టాలు, ఆనందం,ఇంద్రియాలు, బుద్ది వాటివే. కీటకాల్లో అనేక రకాలు. పక్ష్యులలో - చేపల్లో - జంతువుల్లో అనేక బేధాలు వున్నాయి. అట్లానే మనుష్యులలో వున్నాయి. దేశం వల్ల, రేస్ వల్లా పరిస్థితుల వల్ల కలిగే బేధాలు కాక మనిషికి మనిషికి ముఖం లో -- కంఠం లో దేహాకారం లో... రేఖలలో, రుచులలో, గుణాలలో బేధాలున్నాయి. ఈ బేధాల్ని మత ప్రవక్త లు నీతి ప్రవక్త లు ఒప్పుకోరు. సర్వ మానవులకు ఒకటే మత విశ్వాసం, ఒకటే నీతి, చట్టము విధిస్తారు. ఒకరికి కుదిరిన మందు ఇంకొకరికి కుదురుతుందని, ఒకరికి ఆనందమిచ్చిన విషయం ఇంకొకరికి ఆనందమిచ్చి తీరాలని మూఢాభిప్రాయం ప్రజలనికా వదల లేదు. అసంఖ్యాకాలైన ఆనందాలిని, అభిరుచులను, సౌందర్యాలను ఏర్పరిచిన సృష్టి కొల్లబోలేదు.... వాటినన్నిటిని వివిధ రీతుల అనుభవించేందుకే వివిధాలైన స్వభావాలను సృష్టించింది. ఏకత్వం, సమానత్వం సృష్టి సూత్రానికే విరుద్ధం.&lt;br&gt;&lt;br&gt;ఒక కాలం లో దేశాలకీ, సంఘాలికి సరిపడిన నీతి, ఆచారం ఇంకో కాలం లో కూడా సరిపడి తీరాలని, ఒక దేశానికి జాతికి అనుకూలించిన పరిస్తితులు ఇంకో దేశానికి జాతికి అనుకూలించాలని వాదించే వారు అనేకులు. ఎట్లా మనిషి మనిషి కు రూపము, బుద్ది, మారుతుందో అట్లానే వారి స్వభావాన్ని, సంస్కారాన్నీ, బుద్ధి ని బట్టి నీతి ఆనందం మార తాయంటే అంగీకరించరు. థియరీ లో అంగీకరించినా ఆచరణ లో ఒప్పుకోరు.&lt;br&gt;&lt;br&gt;ఈ మత సిద్ధాంతులు, నీతి ప్రవక్త లు,ప్రతి వారమూ సాయింత్రమూ వేదిక నించి, రోడ్డు మూలల నుంచి వుపన్యాసాలిచ్చే దేవ భృత్యులూ ఎవరికి తోచినట్లు ఆనందపడే విధాలు ప్రకటిస్తూ వుంటారు.&lt;br&gt;&lt;br&gt;&lt;br&gt;"సత్యం చెప్పండి బాధలన్నీ పోతాయి" " నా గీతాలను చదవండి", క్రీస్తు ను నమ్మండి", "యోగం చెయండి", "తొట్టి వైద్యం", కార్కు టిప్పు సిగిరెట్ట్లు," , " చచ్చిన వారితో సంభాషణ" " అపక్వాహారం", "సర్వ భాతృత్వం" --తలనూనెలు - స్వరాజ్యం, -- లైబ్రరీలు, " ఇట్లాంటి వాటి ద్వారా వేనవేలు చిరతరానందాన్ని ప్రపంచాలకు ప్రకటిస్తున్నారు.&lt;br&gt;&lt;br&gt;&lt;br&gt;ఇవన్నీ కూడా ఆనందాన్ని ఇచ్చే మాట నిజమే కాని కొన్ని కొన్ని కొందరికి మాత్రమే ఇస్తాయి. కాకి, చచ్చిన ఎలకను తింటే ఆనందమని ఏనుక్కి చెప్పి, చేపలా నీటిలో ఈదమని నక్క కు చెప్పినట్లు వుంటుంది. ప్రతి వాడు తన స్వభావానికి, తన గుణానికి ఏ ఆనందం కావాలో అవి కనుక్కోవాలి. ఆ స్వభావం ఆనందం వైపు ఈడుస్తుంది. కాని ఈ ప్రకటనలు చూసి మోస పోతారు. ఈ ప్రకటనలలో ముఖ్య మైనవి శాస్త్రాలు,, నీతులు, ఆచారం, ధనం, అధికారం మొదలైన భ్రాంతులు. ఒక యోగి వచ్చి ఆసనం చూపగానే అందరూ ఆసనాలు ప్రారంభిస్తారు. పండితులు వచ్చి జుట్టు గొరిగించమనగానే గొరిగిస్తారు. శాంతి లేక కొట్టూకునే ధనవంతుడు భార్య కావాలని యేడిచి పెళ్ళి చేసుకుని "ఎందుకు చేసుకున్నానని" యేడుస్తాడు. పిల్లలు లేరని ఏడ్చే వాళ్ళు,, వుద్యోగం చేస్తూ ఎన్నడు నవ్వని దురదృష్ట వంతుడు, ప్లీడరై కవుల వెంట పరుగెత్తే రసికుడు, పెళ్ళి చేసుకుని నమ్మకం గా నిలువలేని స్త్రీ, చదువుకుని ఆరోగ్యం పోగొట్టుకున్న రోగి,&lt;br&gt;కధలు చదివి, సినిమాలు చూసి భ్రమసి ఇల్లు వదిలి పరుగెత్తి తిరిగి వొచ్చిన జోగి, -- అందరూ, ఇట్లాంటి మూర్ఖులు - తమ ఆనందం తెలీక మాటలు నమ్మి మోసపోయిన ధౌర్భాగ్యులు,. తనకు లేని వస్తువు ఆనందం ఇస్తుందనుకోవటం ఈ భ్రమలలో ముఖ్య మైనది.&lt;br&gt;&lt;br&gt;&lt;br&gt;"ఈ పెళ్ళి నరకం " రా అని ఎంత మంది ఎంత చెప్పినా బాల బ్రహ్మచారి ససేమిరా నమ్మడు. " నీ పెళ్ళాన్ని వదలవేం?" అంటాడు. "ధనం వల్ల సౌఖ్యం లేదు" అని ధనికుడెంత అరిచినా బీదవాడు నమ్మడు. "ధనమంతా నాకియ్యవే" --అంటాడు. ఏ ఆనందం రాకపోయినా ఆ పెళ్ళాన్ని, ధనాన్ని వొదిలే ఆత్మబలం వాళ్ళకు లేదనే సంగతి వీళ్ళకు తెలీదు.&lt;br&gt;&lt;br&gt;&lt;br&gt;కొందరికి దేశ విప్లవం, కొందరికి తిండి, కొందరికి ప్రేమ, కవిత్వం, తగాదాలు, - నిద్ర - ఇట్లా అనేక ఆనందాలు వున్నాయి. తత్వాన్ని బట్టీ మారుతో, ఎవరు చెప్పిన మాట వినకుండా, తన స్వభావాన్ని ఇన్ స్టింక్ట్ ను నమ్ముకుంటే, ఏ మనిషికి అతని ఆనందమేదో స్పృష్టమవుతుంది. ఏ మృగానికి దాని ఆహారమేదో అర్ధమైనట్లు... కాని ఈ మనుష్యులలో జన్మమంతా మాంసం తినే ఆవులు, గడ్డి మేసే సింహాలూ వున్నాయి. -- పైగా అజీర్నమెందుకా అని ఆవు అనేక రకాల మాసం రుచి చూస్తుంది. సిం హం రక రకాల గడ్డి తెప్పించుకుని మేస్తుంది. కాని ఆ గడ్డిని ఇది ఆ మాంసాన్ని అది వొదిలే తెలివితేటలు కాని, ధైర్యం కాని, శక్తి కాని వాటికి వుండవు.&lt;br&gt;&lt;br&gt;కవిత్వం చదివి " ఆహా సూర్యాస్తమయం యెంత అందమైనది ! నేను చూడనే లేదే " అని ఒకడు సాయింత్ర్రం గోదావరి గట్టున కూర్చుంటే ఆ ఆనందం వొస్తుందా? ఆవడలో, ఇంటి తగాదాలో, సినిమా కథలో, ఏదో తలుచుకుంటూ కూచుంటాడు అంత సేపు...!&lt;br&gt;&lt;br&gt;&lt;br&gt;అట్లానే కొందరికి త్యాగం ఆనందమిస్తుంది -- కొన్ని పరిస్తుతులలో. కాని ప్రతి వుపన్యాసకుడు, గ్రంధకర్తా త్యాగం చెయ్యమనే వాడే -- కవిత్వానికని, సత్రానికని, కొడుకు పెళ్ళికని, దేశానికనీ, పత్రిక్కి చందా కని త్యాగం రాదు. ఏ స్వభావానికి ఏ త్యాగం ఆనందమిస్తుందో అదే అవసరం, ఆరోగ్యమూ... కొందరికి అసలు త్యాగమే పనికి రాదు. చాలా మంది త్యాగాలు ఏదుస్తూ చేస్తారు. మతము ధర్మము డ్యూటి అని పేర్లు పెట్టి త్యాగాలు చేస్తారు. సాధారణం గా తల్లులు భార్యలు చేసే త్యాగాలు ఇట్లాంటివే. ఎవరికే త్యాగం అవసరమో వళ్ళ ఆనందమే నిర్ణయించాలి. ఒక స్త్రీ తన భర్త ను వదిలి పిల్లలను వదిలి పనికిమాలిన ప్రియుడి వెంట వెళుతుంది. ఇంకో స్త్రీ పనికి మాలిన భర్త కోసం ప్రియుణ్ణీ లోకాన్నీ, పిల్లలనీ వదులుకుంటుంది. ఇంకో ఆమె బిడ్డ కోసం భర్త ని, సంఘాన్ని, నీతి ని వదులుతుంది.. వీటిల్లో సంఘానికి నచ్చినవి మెచ్చుకుంటారు. తక్కినవాటిని ఖండిస్తారు. కాని ఏది ధర్మమో, ఏది ఆనందాన్ని ఇస్తుందో ఎవరికి వారు నిర్ణయించుకోవలసిందే కాని మనుష్యులు కాని శాశ్త్రాలు కాని నిర్ణయించలేవు... ఎందుకంటే ఆనందమివ్వని ధర్మం నీ ధర్మం కాదు, ఇంకొకడిదీ,&lt;br&gt;&lt;br&gt;దేశానికి ప్రతివాడు త్యాగం చెయ్యాలని అంటారు. అక్కర్లేదు అంటే తిడతారు. ఎవరి హృదయం దేశభక్తి తో పరవశమౌతుందో వాళ్ళు సర్వము త్యాగం చెయ్యనే చేస్తారు. ఇది మన ధర్మం కనక చేయాలి అనే ప్రసక్తే వుండదు... "ఇది నా ధర్మం" అనుకునేప్పటికే ఇతరులు విధించిన ధర్మమని వ్యక్తమవుతుంటుంది... అట్లా దేశభక్తి వల్ల అనందం రాని వాళ్ళు ధర్మమని కీర్తికని, పక్కవాడు చేసేడని, చాలామంది చేసేరు... త్వరలోనే చింతించారు... వారి స్వభావం ఆ త్యాగానికి తగినది కాదు గనుక.&lt;br&gt;&lt;br&gt;సుఖము బాధ పరిస్తితులు తెచ్చి పెడుతు వుంటాయి, చాలా మంది ఏమి ఆలోచించకుండా అనుభవిస్తూ బతుకుతారు. తాము ఎంత వరకు ఆ బాధలకు కారణం, తప్పించుకోవటానికి తమ ప్రయత్నమెంతవరకు వుపయోగపడుతుందో, యోచించరు. కర్మ లోనూ, జ్యోతిష్కం లోను నమ్మకం ఈ నిద్ర కు తోడ్పడి, జోల పాడుతుంది. జీవితం లో సంతోషం లేనప్పుడు కొత్త సంతోషము కల్పించుకోగలం. బాధలు తటస్తించినప్పుడు నిగ్రహించుకోగలం. బాధను ఎదిరించి పోట్లాడితే చాలా వరకు లోబడుతుంది. కాని ఆ జ్ఞానము శక్తీ చాలా కొద్ది మందికే వున్నాయి.&lt;br&gt;&lt;br&gt;లోకం సౌందర్యాన్ని కల్పిస్తుంది., కాని అనుభవించమని బలవంతపెట్టగలదా? అట్లానే జీవితం కష్టాలను కల్పిస్తుంది, కాని అనుభవించమని బలవంత పెట్టలేదు.&lt;br&gt;&lt;br&gt;వెయ్యకు తొమ్మిదివందల తొంభైమందికి ప్రత్యేకం గా ఏదో అందరాని ఆనందాన్ని సాధించాలనే ఆర్జి వుండదు. ఇంకా మృగాల స్తితి లోనే వున్నారు. సుఖం గా తినటమూ, కనడమూ , చావడమూ , వాళ్ళు చేయవలసిందల్లా. అదే వాళ్ళ ఆనందము. కాని ఆ సంగతి గమనించరు. ఘన కార్యాలు చేసిన వాళ్ళ గురించి విని కని, చదివీ, తమకు లేని శక్తులు వున్నయనుకుని అనుసరించ పోతారు. ప్రయత్నించి విఫలులైన బోసులూ, శాండో లు, శుక మహర్షులు, రవీంద్రులు, I.C.S లు ఎందరో వున్నారు మన మధ్య. నరకం, స్వర్గం సంగతులు విని, భయపడి, ఆశపడి భక్తి ని, వైరాగ్యాన్ని, నటిస్తారు. దాని వల్ల రోగాలు బాధలు అప్పులు ఇన్ని పడతారు. ఎంత తన్నుకున్న శాస్త్రాలు ఎంత ఘోషించినా ఎన్ని తత్వాలు పాడినా అందరు విరాగులు కాదు, ధర్మాత్ములు కారు. ఆ పాడే వాళ్ళకు తెలుసు "అన్నళ్ళీ ముచ్చటలు - తనువులు శాశ్వతమా" అని పాడి విరక్తి పుట్టిస్తారు. కాని ఒక్క గుప్పెడు బియ్యం మీదో, ఒక్క కానీ మీదో మనకు విరక్తి కలిగితే చాలు ఆ పూటకి, వాడికి తృప్తి. తమ జీవితం లో ఆనందం ఎట్లా కలుగుతుందో తెలిసినా, ఆ ఆనందం కోసమే ప్రయత్నం చేసి ఆటంకాలను వదులుచుకునే వాళ్ళూ చాలా కొద్ది మంది. ప్రతి పని విషయమై కూడా 'ఇది నా ఆత్మ కు ఆరోగ్యమా కాదా? నాకు లభ్యమైన కాలాన్ని, శక్తి ని, ధనాన్ని ఆనంద రూపం గా మారుస్తున్నానా లేదా?' అని విమర్శించరు. మొహమాటం, ప్రతిష్టా, భేషజం, కపటమూ ఇన్నీ అడ్డం వస్తాయి.&lt;br&gt;&lt;br&gt;వొంటి నిండా చీము తో, చెయ్యి ఎత్తలేక వొణికే వాడికి కానీ ఇవ్వము. మనకి అక్కర్లేని పత్రికకు చందాగా అప్పుడే ఇంకొకడు నాలుగు రూపాయిలు పట్టుకుని పోతాడు.&lt;br&gt;&lt;br&gt;మనం మీటింగులకు ప్రెసిడెంట్లు గా వుండటం, అనుష్టించే కర్మ కలాపాలు, తగాదాలు, అన్నీ ఏ మాత్రమైనా ఆరోగ్యాన్ని ఇస్తాయా? వుత్తమ లోకం లో నమ్మకం లేని వాడు బ్రాహ్మల కాళ్ళు కడిగి తద్దినం పెడతాడు. బ్రాహ్మణ్ణి తిట్టి కమ్మ బ్రాహ్మణ్ణి పూచ్చేసి దక్షిణలిస్తాడు.&lt;br&gt;&lt;br&gt;మన వేషం, బట్టలు, జుట్టు, తిండి, మనం పెట్టే భోజనాలు, ఆడే మాటలు, అన్నీ ఏమీ ఆనందం ఇవ్వని శుష్కమైన ప్రదర్శనాలు --ఎన్ని!&lt;br&gt;జీవనమంతా వాటితోనే వృధాగా గడిచిపోతుంది. మనకు ఆనందం ఇచ్చే వాటిని అనుభవించటానికి జంకుతాము. ఎవరు చూస్తున్నారో అనే భయం తో, చక్కని మనిషి నడుస్తో వుంటే తేరి చూడ్డానికి భయం, భోగమాట చూడ్డానికి భయం, బట్టలు లేని బొమ్మలు, వెంకటాచలం కధ లు ఇవన్నీ రహస్యం గా ఆనందిస్తాము.&lt;br&gt;&lt;br&gt;ఇట్లా ఏళ్ళకు ఏళ్ళు గడిచి పోతాయి. మనకు ఆనందం వుంది అని ఇతరులు అనుకోవటానికి ఆనందాన్ని ధార పోస్తాం. మనం కట్టే డాబైన ఇల్లు, మోసే బంగారు నగలు, చేసే గొప్ప పెళ్ళిళ్ళు, ఖర్చులు, కష్టాలు, ఏడిపించుకు తినే అల్లుళ్ళు, అన్నీ ఒక రవ్వ ఆనందాన్ని ఇవ్వవు. కొడుకుని ద్వేషిస్తాము; వొదిలే ధైర్యం లేదు, భార్యలు భర్తలను, భర్తలు భార్యల్నీ,వొదిలే ధైర్యం లేదు. ఇష్టం లేని వాడు వొస్తే వొద్దని చెప్పే ధైర్యం లేదు.&lt;br&gt;&lt;br&gt;నీ జీవితం దేనికి, ఏ ఆనందానికి ఏర్పడిందో చూడు. ఆ ఆనందం నీతి గాని కాక పోని, ధర్మం కానీ, అధర్మం కానీ, వున్నతం కానీ కాక పోనీ .... అన్నిటినీ -- బంధువుల్నీ, కులాన్నీ, నీతిని, చివరకు నీ సౌఖ్యాన్ని, అన్నిటిని త్యజించి అవసరమైతే ఆ అధర్మాన్ని ఆశ్రయించు. ఆ ప్రయత్నమే, ఆ కష్టమే, ఆ రాపిడే ఆత్మకు ఆనందాన్ని ఇస్తుంది. నీ ఆత్మ లో కొత్త విస్తీర్ణం, నీ కళ్ళ ముందు కొత్త లోకాలు వెలుగుతాయి. తప్పు కానీ, ఒప్పు కాని వెనుక ముందు చూడకు. తప్పైతే దిద్దుకోవటానికి చాలా కాలముంది. వెనుకముందులు యోచించే చచ్చు బతుకు కంటే ధీరత్వంతో ముందుకు సాగి గోతిలో పడేవాడికి ఎక్కువ ఆనందముంది ఈ లోకం లో.&lt;br&gt;&lt;br&gt;ఈ ఆనందాల్లో డిగ్రీలున్నాయి. పేడ తింటో సుఖించే పురుగూ, కాంతిలో ఎగురుతు అరిచే చిలుకా, డబ్బు లెక్క పెడుతో తన్మయత్వం లో పడే పిసినారి, దేశం కోసం గుండు దెబ్బ తిని చస్తో ధన్యుణ్ణనుకున్న యోధుడూ, స్త్రీ బొమ్మ ను చెక్కి తను కల్పించిన ఆనందాన్ని తాను చూసి మూర్చిల్లే శిల్పీ, అనంత విశ్వం లో తన ఆత్మ ను కలిపి సర్వ జీవుల సుఖ దుఖాలు తనలో అనుభవించగల యోగీ, అందరూ ఆనందాన్నే అనుభవిస్తున్నారు. కానీ అన్నీ ఒకటే డిగ్రీలోవి కావు. లోకం చూసిన కొద్దీ ఈ అనుభవం విషయం లో కూడా 'లైఫ్' లో గొప్ప 'ఎవల్యూషన్ ' కలుగుతున్నట్లు తోస్తుంది.&lt;br&gt;&lt;br&gt;కొత్త ఆనందాలను సగం సగం తోచి తామందుకోలేని సౌందర్యాలనూ, అనుభవించే విధం తెలీక, తపన పడి, జీవులు తమ ఇంద్రియ శక్తి ని మార్చుకోవాలని తమకు తెలీకుండానే ప్రయత్నించి ఒక రూపం నుంచి ఇంకో రూపం పొందుతున్నట్లు తోస్తుంది. రెక్కల పురుగు ఇంకా విస్తీర్ణత ను కోరి కోరి చిలుక కావొచ్చు. పిల్లి ఇంకా బలాన్ని గభీరాన్నీ కోరి సిమ్హం కావొచ్చును. అట్లాగే ఒకడు తనలోలేని శక్తుల్నీ కోరి కోరి ఏ జన్మలోనైతేనేం, ఏ లోకంలోనైతేనేం, పాటకుడూ, వస్తాదూ, యోగీ, కిన్నరుడూ లేక రాక్షసుడుగా మార వచ్చు. అట్లాంటి మార్పు రాక పోతే, నా హృదయం లో చూచాయ గా తోచే ఈ వున్నతానందాలూ, నేను కలలు గనే ఈ లోకాలకి సంబంధించని సౌందర్యాలు, నేను పొందాలని కోరే మానవాతీత శక్తులూ ఇవన్నీ అర్ధ విహీన మవుతాయి. భోజనమూ, ఆరోగ్యమూ, ధనమూ వుండి కూడా ఆత్మలు ఎందుకిట్లా తమకే తెలీని ఆరాటాలతో బాధ పడాలి? పాకే బిడ్డ ఎన్ని సార్లు పడి దెబ్బ తిన్నా నడవాలని ఎందుకు ప్రయత్నం చెయ్యాలి? అదేననుకుంటా, ఈ సృష్టి సూత్రం. మనం అందుకోగలిగి నంతవరకు ఈ అభివృద్ధి ఒక్క జీవితం లోనే నిశ్చయం గా పొందగలుగుదుమనుకునే వాళ్ళు మూర్ఖులు, జన్మలనేవి వుంటే, ఎప్పటికో సాధించవలసిందే. ఏమైనా, ఏ ఆనందానికిగాని చేసే ప్రయత్నం కూడా ఆనందమివ్వాలి. ఇవ్వకపోతే నీ ఆనందం అది కాదు.&lt;br&gt;&lt;br&gt;"నీకింకేం కావాలి, ఎందుకట్లా వెతుకుతా?" వంటారు మిత్రులు.&lt;br&gt;&lt;br&gt;'కారణం లేని ఈ ఆరాటం -- ఈ సృష్టికి అర్ధమేమిటి, నీతి ఏమిటి, పాపమేమిటి, నేను నమ్మేవి చేసేవి సత్యమా -- అనే మీమాంస, కొత్త సౌందర్యాలకోసం, ఎండమావుల కోసం వలే, రెప్పలార్చుకుంటో పరుగులు: మనకు కానిది, మనం అందుకోలేనిది, మనం మిస్ అయింది, ఎంతో లోకం, ఎంతో జీవితం, కాలం, అందం వృధా పోతుందనే దిగులు -- ఇవేమి లేకుండా తక్కిన వారివలే బతికి కూచోకూడదా ?' అని అడుగుతుంది శ్రమపడ్డ ఆత్మ.&lt;br&gt;&lt;br&gt;&lt;br&gt;కాని ఏమి లాభం? ఎందుకా విధం గా ఆ రెక్కలు కొట్టుకుంటో పరుగెత్తుతావు? నేను నీకు పళ్ళు పెడతాను, ఆడ చిలుక ను తెస్తాను, నా ఇంట్లో వుండమని చిలక నడిగి ఏమి లాభం... ???&lt;br&gt;&lt;br&gt;&lt;br&gt;More stories &amp;amp; essays.... &lt;a href="http://www.avilpage.com/2014/04/my-favorite-stories-essays-of-chalam.html"&gt;నాకు నచ్చిన చలం కథలు, వ్యాసాలు&lt;/a&gt;&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;/div&gt;</description><category>chalam</category><guid>https://avilpage.com/2014/04/aanandam-essay-by-gudipati-venkatachalam.html</guid><pubDate>Sun, 20 Apr 2014 11:16:00 GMT</pubDate></item><item><title>4 Delightful Short Zen Stories About Women &amp; Love!</title><link>https://avilpage.com/2014/03/4-delightful-short-zen-stories-about.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: small; font-weight: normal;"&gt;Reading stories is my all time favorite hobbies. I read a lot of short stories and I am sharing a few best Zen stories I have been reading recently.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: small; font-weight: normal;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;1. Carrying A Woman!&lt;/h3&gt;Tanzan and Ekido were once travelling together down a muddy road. A heavy rain was still falling.&lt;br&gt;&lt;br&gt;Coming around a bend, they met a lovely girl in a silk kimono and sash, unable to cross the intersection.&lt;br&gt;&lt;br&gt;"Come on, girl," said Tanzan at once. Lifting her in his arms, he carried her over the mud.&lt;br&gt;&lt;br&gt;Ekido did not speak again until that night when they reached a lodging temple. Then he no longer could restrain himself.&lt;br&gt;&lt;br&gt;"We monks don't do near females," he told Tanzan, "especially not young and lovely&lt;br&gt;ones. It is dangerous. Why did you do that?"&lt;br&gt;&lt;br&gt;"I left the girl there," said Tanzan. "Are you still carrying her?"&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;2. If You Love, Love Openly&lt;/h3&gt;Twenty monks and one nun, who was named Eshun, were practicing meditation with a certain Zen master.&lt;br&gt;&lt;br&gt;Eshun was very pretty even though her head was shaved and her dress plain. Several monks secretly fell in love with her. One of them wrote her a love letter, insisting upon a private meeting.&lt;br&gt;&lt;br&gt;Eshun did not reply. The following day the master gave a lecture to the group, and when it was over, Eshun arose. Addressing the one who had written her, she said: "If you really love me so much, come and embrace me now."&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;3. Too Much Love&lt;/h3&gt; An aged monk, who had lived a long and active life, was assigned a chaplain's role at an academy for girls. In discussion groups he often found that the subject of love became a central topic.&lt;br&gt;&lt;br&gt;This comprised his warning to the young women: "Understand the danger of anything-too-much in your lives. Too much anger in combat can lead to recklessness and death. Too much ador in religious beliefs can lead to close mindedness and persecution. Too much passion in love creates dream images of the beloved - images that ultimately prove false and generate anger. To love too much is to lick honey from the point of a knife."&lt;br&gt;&lt;br&gt;&lt;div&gt;&lt;div&gt;"But as a celebate monk," asked one young woman, "how can you know of love between a man and a woman?"&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;"Sometime, dear children," replied the old teacher, "I will tell you why I became a monk."&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;4.  Change!&lt;/h3&gt;&lt;div&gt;&lt;div&gt;A Chinese emperor known for his foul temper entered the bedroom of his soon-to-be-bride, who was one of the most beautiful women in all of China. She was being made to marry him against her will, as her parents were forcing her into it. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Little did the emperor know however that she had also been taught by wise sages as a child. She sat expressionless, staring at the wall. "Hello, pretty," he said to her, but she didn't respond.&lt;/div&gt;&lt;div&gt;"I said hello to you, and you will respond when I address you, do you understand me??" he snarled. But still, she didn't reply.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Most people would have answered him by now, so despite himself he grew curious, and gruffly asked, "What is it you are thinking?"&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Finally she answered him. "Two things. One, that I do not wish to marry you because you are so callous and mean-spirited. And the other thing, is that I was wondering if you have it within your power to have a certain something changed."&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;"What?!" the emperor exclaimed with outrage. "You bitch! How dare you question my authority! ... But ... I admit I'm curious. Since I have it within my power to snap my fingers and whatever I command within my kingdom will be obeyed, what is it you are wondering if I could change?"&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;"Your attitude," she replied. And with that she got up and walked out of the room, leaving him in stunned silence.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>zen-stories</category><guid>https://avilpage.com/2014/03/4-delightful-short-zen-stories-about.html</guid><pubDate>Mon, 31 Mar 2014 07:27:00 GMT</pubDate></item><item><title>2048 Game - Tips To Make a 2048 Tile Easily &amp; Quickly</title><link>https://avilpage.com/2014/03/2048-game-tips-to-make-2048-tile-easily.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h2 style="text-align: left;"&gt;2048 Game:&lt;/h2&gt;&lt;div&gt;So, You got addicted to 2048 and wondering how to make 2048 tile? As long as you don't know the strategy its a nightmare. Once you know that, its pretty easy and I bet you can make 2048 tile every time you play a game. Sounds good? Lets get started.&lt;br&gt;&lt;br&gt;Warning: This is How I play the game and I can make 2048 tile  every time I play this.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h2 style="text-align: left;"&gt;Strategy: Goal &amp;amp; The Path&lt;/h2&gt;&lt;div&gt;Now, lets look at the game a bit differently. Its very tedious( and time consuming ) to look at all 16 tiles for each and every move we make while playing the game. Actually we don't have to. Take a look at the pictures below.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-eu3-CfYFsXI/UzW_som8h9I/AAAAAAAAKRc/uxAovBqC__4/s1600/2048-hack-strategy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-eu3-CfYFsXI/UzW_som8h9I/AAAAAAAAKRc/uxAovBqC__4/s1600/2048-hack-strategy.png" height="400" width="240"&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-8VufyIbQa00/UzWjbycHCiI/AAAAAAAAKRA/vWHEkRvG2Ho/s1600/2048-guide-walkthrough.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F1.bp.blogspot.com%2F-8VufyIbQa00%2FUzWjbycHCiI%2FAAAAAAAAKRA%2FvWHEkRvG2Ho%2Fs1600%2F2048-guide-walkthrough.png&amp;amp;container=blogger&amp;amp;gadget=a&amp;amp;rewriteMime=image%2F*" width="378"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;The Goal - The tile where 2048 will  be formed.&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;The Path - A few tiles which we will use to make goal.&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;Now don't worry much about the remaining tiles.&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;How To Make 2048 Tile?&lt;/h2&gt;&lt;br&gt;1. Start the game.&lt;br&gt;&lt;br&gt;2. Move the first tile to the goal position and keep adding remaining tiles to this.&lt;br&gt;&lt;br&gt;3. Do not move the goal tile unless you have no other choice.&lt;br&gt;&lt;br&gt;4. DO NOT MOVE THE GOAL TILE UNLESS YOU HAVE NO OTHER CHOICE.&lt;br&gt;&lt;br&gt;5. Move the next tiles to path in DECREASING ORDER ONLY.&lt;br&gt;&lt;br&gt;6. Make sure the goal is always the biggest tile and tiles in the path must be in decreasing order.&lt;br&gt;&lt;div&gt;    Example: {Goal:16, Path: 8,4,2} or {Goal 1024; Path:512,256,256 as show in the pic}&lt;br&gt;&lt;br&gt;7. Go on adding the tiles in the path to the goal.&lt;br&gt;&lt;br&gt;That's it.&lt;br&gt;&lt;br&gt;If you follow the above rules and play the game a few times You will make 2048 tile easily. Good luck.&lt;br&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;Tips:&lt;/h2&gt;&lt;/div&gt;&lt;div&gt;1. Instead of pushing tiles around stick to 2 swipes only. &lt;/div&gt;&lt;div&gt;While I play the game, I swipe from top to bottom and right to left only. If these two are not possible then I swipe from top to bottom or left to right depending up on the tiles.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;2. Always keep the high valued tile in bottom left and keep adding the remaining tiles in descending order from bottom to top as shown in the figure.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;For Geeks: If you want to solve 2048 programatically check this &lt;a href="http://stackoverflow.com/questions/22342854/what-is-the-optimal-algorithm-for-the-game-2048" target="_blank"&gt;Stackoverflow Q &amp;amp; A&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Check this video on how to make 2048 tile!&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://i1.ytimg.com/vi/bUc6qyn57A4/0.jpg"&gt;&lt;param name="movie" value="https://www.youtube.com/v/bUc6qyn57A4?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/bUc6qyn57A4?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>gaming</category><guid>https://avilpage.com/2014/03/2048-game-tips-to-make-2048-tile-easily.html</guid><pubDate>Fri, 28 Mar 2014 13:44:00 GMT</pubDate></item><item><title>My Tribute To Relecura!</title><link>https://avilpage.com/2014/03/my-tribute-to-relecura.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;

    &lt;div style="text-align: left;"&gt;
      &lt;div&gt;
        &lt;i&gt;&lt;b&gt;tribute&lt;/b&gt; (ˈtrɪbjuːt) noun &lt;/i&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;i&gt;A gift or statement made in acknowledgment, gratitude, or admiration.&lt;/i&gt;&lt;br&gt;
        &lt;i&gt;&lt;br&gt;&lt;/i&gt;
      &lt;/div&gt;&lt;span style="font-family: inherit;"&gt;&lt;i&gt;" Feeling gratitude and not expressing it is like wrapping a present and not giving it. "&lt;/i&gt;&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style="text-align: left;"&gt;
      &lt;div style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;
         &lt;i style="font-family: inherit;"&gt;- William Arthur Ward&lt;/i&gt;
      &lt;/div&gt;&lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;
      More than 100 days of have passed since I joined &lt;a href="http://www.relecura.com/" target="_blank"&gt;INDUS Techinnovations&lt;/a&gt; and I am pretty excited to
      be a part of this company. I thought of doing something for our company.&lt;br&gt;
      &lt;br&gt;
      So, I brought some Rubik Cubes and made a mosaic.&lt;br&gt;
      &lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://1.bp.blogspot.com/-yXyS8k6oLiI/UxMnZfPxCJI/AAAAAAAAKPM/TM-m0pyFvfc/s1600/bulk-rubik-cubes-india.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-yXyS8k6oLiI/UxMnZfPxCJI/AAAAAAAAKPM/TM-m0pyFvfc/s1600/bulk-rubik-cubes-india.jpg" height="300" width="400"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;a href="http://2.bp.blogspot.com/-KB9wzHfkNqs/UxMoNDNluzI/AAAAAAAAKPY/NWkJDJ6vmSg/s1600/rubik-cube-art.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-KB9wzHfkNqs/UxMoNDNluzI/AAAAAAAAKPY/NWkJDJ6vmSg/s1600/rubik-cube-art.png" height="266" width="400"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div class="separator" style="clear: both; text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div class="separator" style="clear: both; text-align: left;"&gt;
        &lt;a href="http://2.bp.blogspot.com/-WRBW9-Lpl94/UxMoQE2O5zI/AAAAAAAAKPs/5WrptT6ZKok/s1600/rubik-cube-mosaic.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-WRBW9-Lpl94/UxMoQE2O5zI/AAAAAAAAKPs/5WrptT6ZKok/s1600/rubik-cube-mosaic.png" height="230" width="400"&gt;&lt;/a&gt;
      &lt;/div&gt;

      &lt;div class="separator" style="clear: both; text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://4.bp.blogspot.com/-Mv5gU2OVbl0/UxMoNJA5wVI/AAAAAAAAKPg/RjCe8qNP3g4/s1600/rubik-cube-mosaic-india.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Mv5gU2OVbl0/UxMoNJA5wVI/AAAAAAAAKPg/RjCe8qNP3g4/s1600/rubik-cube-mosaic-india.png" height="187" width="400"&gt;&lt;/a&gt;
      &lt;/div&gt;&lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://2.bp.blogspot.com/-WRBW9-Lpl94/UxMoQE2O5zI/AAAAAAAAKPs/5WrptT6ZKok/s1600/rubik-cube-mosaic.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;br&gt;&lt;/a&gt;
      &lt;/div&gt;&lt;br&gt;
      &lt;br&gt;
      &lt;img border="0" src="http://2.bp.blogspot.com/-ueF0BOfJ8z8/UxMoMnur_hI/AAAAAAAAKPU/P7fuIh6uMHI/s1600/rubik-cube-art-logo.png" height="187" width="400"&gt;&lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;a href="http://3.bp.blogspot.com/-Or5EjMfBn6s/UxMoS0BBGPI/AAAAAAAAKP0/DJu3_uYoxqU/s1600/rubik-cube-mosaics.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Or5EjMfBn6s/UxMoS0BBGPI/AAAAAAAAKP0/DJu3_uYoxqU/s1600/rubik-cube-mosaics.png" height="211" width="400"&gt;&lt;/a&gt;
      &lt;/div&gt;&lt;br&gt;

      &lt;div class="separator" style="clear: both; text-align: center;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;
        &lt;tbody&gt;
          &lt;tr&gt;
            &lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-5lJdZy18CO0/UxMrckqp7LI/AAAAAAAAKQQ/w96cXgmfWjI/s1600/relecura-logo-rubik-cube-mosaic.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-5lJdZy18CO0/UxMrckqp7LI/AAAAAAAAKQQ/w96cXgmfWjI/s1600/relecura-logo-rubik-cube-mosaic.jpg" height="300" width="400"&gt;&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;

          &lt;tr&gt;
            &lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="font-size: small; text-align: left;"&gt;
                &lt;a href="https://avilpage.com/p/rubik-cube-mosaics.html"&gt;Rubik Cube Mosaic&lt;/a&gt; of Relecura Logo!&lt;/span&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        *Thanks to &lt;a href="https://www.facebook.com/shanmukha.sreenivas.3" target="_blank"&gt;Sreenivas&lt;/a&gt;, &lt;a href="http://www.relecura.com/management.php" target="_blank"&gt;George&lt;/a&gt;, &lt;a href="http://www.relecura.com/management.php" target="_blank"&gt;Nikhil&lt;/a&gt; and all our team.
      &lt;/div&gt;

      &lt;div style="text-align: left;"&gt;
        &lt;br&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;</description><category>rubiks-cube</category><guid>https://avilpage.com/2014/03/my-tribute-to-relecura.html</guid><pubDate>Sun, 02 Mar 2014 07:54:00 GMT</pubDate></item><item><title>Best Way To Restore USB Drive Back to Full Capacity!</title><link>https://avilpage.com/2014/02/best-way-to-restore-usb-drive-back-to.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    If You have used USB Drive to install a Ubuntu or any Linux Distros on your PC, Your pen drive might lost the space. Whether Your pen drive is 4GB/8Gb/16GB
    or whatever it will reduce to the size of the ISO file You have used normally to 700MB. You can format this pendrive but still you will get only 700MB. So,
    what now?&lt;br&gt;
    &lt;br&gt;
    There is a simple trick to recover pendrive to its full capacity.&lt;br&gt;
    &lt;br&gt;

    &lt;b&gt;What You Need?&lt;/b&gt;

    &lt;br&gt;
    1. A PC with Windows OS.
    &lt;br&gt;
    2. A corrupted USB Drive.
    &lt;br&gt;&lt;br&gt;

    &lt;b&gt;Process: &lt;/b&gt;
    &lt;br&gt;
    1. Open Run ( Windows + R ).
    &lt;br&gt;&lt;br&gt;
    2. Type Diskpart and press Enter ( diskpart ).&lt;br&gt;
    &lt;br&gt;
    3. Type list disk ( list disk ).&lt;br&gt;
    &lt;br&gt;
    4. Type select disk 1 ( select disk 1 ).&lt;br&gt;
    &lt;br&gt;
    5. Type clean and enter ( clean ).&lt;br&gt;
    &lt;br&gt;
    6. Now you USB will show 0Bytes. Don't panic. Just unplug USB and insert again.&lt;br&gt;
    &lt;br&gt;
    8. The system will prompt for fromat and do format.&lt;br&gt;
    &lt;br&gt;
    Thats it. You have recovered Your USB drive to its full capacity from corruption!!&lt;br&gt;

    &lt;div&gt;
      &lt;br&gt;
    &lt;/div&gt;
  &lt;/div&gt;</description><category>how-to</category><guid>https://avilpage.com/2014/02/best-way-to-restore-usb-drive-back-to.html</guid><pubDate>Tue, 25 Feb 2014 22:00:00 GMT</pubDate></item><item><title>How To Find All Subsidiaries Of A Company?</title><link>https://avilpage.com/2014/02/how-to-find-all-subsidiaries-of-company.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h2 style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;Understanding Subsidiaries:&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;A subsidiary is a company that is completely or partly owned by another corporation that owns more than half of the subsidiary's stock.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;A first-tier subsidiary means a subsidiary/daughter company of the ultimate parent company, while a second-tier subsidiary is a subsidiary of a first-tier subsidiary: a "granddaughter" of the main parent company. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Ford motor company with its tiered subsidiaries is shown below.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;ul style="font-size: 12.727272033691406px; list-style-image: url(data:image/png; margin: 0.3em 0px 0px 1.6em; padding: 0px;"&gt;&lt;li style="margin-bottom: 0.1em;"&gt;&lt;span style="background-color: white; line-height: 1.7em !important;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;b&gt;Ford Motor Company &lt;/b&gt;– Parent company  &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul style="list-style-image: url(data:image/png; list-style-type: disc; margin: 0.3em 0px 0px 1.6em; padding: 0px;"&gt;&lt;li style="margin-bottom: 0.1em;"&gt;&lt;span style="background-color: white; line-height: 1.7em !important;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;b&gt;Ford International Capital LLC&lt;/b&gt; – First-tier subsidiary  &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul style="list-style-image: url(data:image/png; list-style-type: disc; margin: 0.3em 0px 0px 1.6em; padding: 0px;"&gt;&lt;li style="margin-bottom: 0.1em;"&gt;&lt;span style="background-color: white; line-height: 1.7em !important;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;b&gt;Blue Oval Holdings &lt;/b&gt;– Second-tier subsidiary  &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul style="list-style-image: url(data:image/png; list-style-type: disc; margin: 0.3em 0px 0px 1.6em; padding: 0px;"&gt;&lt;li style="line-height: 1.7em !important; margin-bottom: 0.1em;"&gt;&lt;span style="background-color: white;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;b&gt;Ford Motor Company Limited&lt;/b&gt; – Third-tier subsidiary  &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul style="line-height: 1.7em !important; list-style-image: url(data:image/png; list-style-type: disc; margin: 0.3em 0px 0px 1.6em; padding: 0px;"&gt;&lt;li style="line-height: 1.7em !important; margin-bottom: 0.1em;"&gt;&lt;span style="background-color: white;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;b&gt;Ford Component Sales Limited &lt;/b&gt;– Fourth-tier subsidiary  &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;h2&gt;&lt;span style="font-size: large;"&gt;Finding Subsidiaries:&lt;/span&gt;&lt;/h2&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;1. Corporate Sites:&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;The best source to find subsidiaries of a company is its corporate sites itself. Press Releases provide information about recent acquisitions and other information. A lot of companies provide a lot of information about its subsidiaries in their annual Reports&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;2. SEC.gov&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;All companies, foreign and domestic, are required to file registration statements, periodic reports, and other forms electronically through EDGAR. Anyone can access and download this information for free. Here, subsidiaries list is available for most public companies.&lt;br&gt;Example: &lt;a href="http://www.sec.gov/Archives/edgar/data/40545/000119312511047479/dex21.htm" target="_blank"&gt;List of subsidiaries of General Electric at SEC.gov&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;3. Open Corporates&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Opencorporates have information about 60+ million companies. You can search the database and find the parent company. There you can a huge list of subsidiaries for it. &lt;/div&gt;&lt;div&gt;Example: &lt;a href="https://opencorporates.com/placeholders/219443" target="_blank"&gt;List of subsidiaries of General Electric at Opencorporates.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;4. Wikipedia&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;Wikipedia is also most valuable source to find acquisitions and assets of companies. There are a lot of articles covering acquisitions of various companies. In addition to that there a few lists which contain subsidiaries of a company.&lt;br&gt;Example: &lt;a href="https://en.wikipedia.org/wiki/List_of_assets_owned_by_Berkshire_Hathaway" target="_blank"&gt;List of assets owned by Berkshire Hathaway&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/List_of_mergers_and_acquisitions_by_IBM" target="_blank"&gt;List of mergers and acquisitions by IBM&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>how-to</category><guid>https://avilpage.com/2014/02/how-to-find-all-subsidiaries-of-company.html</guid><pubDate>Sun, 23 Feb 2014 23:58:00 GMT</pubDate></item><item><title>చలం కథలు - సీత తల్లి (Seetha Thalli - Gudipati Venkatachalam )</title><link>https://avilpage.com/2014/02/seetha-thalli-story-by-gudipati-venkatachalam.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h2 style="text-align: left;"&gt;&lt;span style="font-family: inherit; font-size: large;"&gt;ముందు మాట: &lt;/span&gt;&lt;/h2&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: inherit; font-size: large;"&gt;చలంగా ప్రసిద్ధుడైన గుడిపాటి వెంకట చలం సుప్రసిద్ధ తెలుగు రచయిత, వేదాంతి మరియు సంఘసంస్కర్త. హేతువాది .ఆధునిక తెలుగు సాహిత్యాన్ని ప్రభావితం చేసిన అతి ముఖ్య వ్యక్తుల్లో చలం ఒకడు. చలం రచనలు చాలా వరకు స్త్రీల జీవితాలను ఇతివృత్తంగా చేసుకుని ఉంటాయి. ముఖ్యంగా సమాజంలో వారికి ఎదురయ్యే శారీరక మరియు మానసిక హింసలు, వాటిని వారు ఎదుర్కొనే విధానాలను చర్చించాడు. చలం రచనలలో ఇతివృత్తమూ, తాత్వికతా, రచనాశైలీ ఆయనకు ఆధునిక తెలుగు రచనా రంగంలో అనన్యమైన స్థానాన్ని సంపాదించిపెట్టాయి. ( Source: &lt;a href="https://te.wikipedia.org/wiki/%E0%B0%97%E0%B1%81%E0%B0%A1%E0%B0%BF%E0%B0%AA%E0%B0%BE%E0%B0%9F%E0%B0%BF_%E0%B0%B5%E0%B1%86%E0%B0%82%E0%B0%95%E0%B0%9F_%E0%B0%9A%E0%B0%B2%E0%B0%82" target="_blank"&gt;వికీపీడియా&lt;/a&gt;  )&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: inherit; font-size: large;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;h2 style="text-align: left;"&gt;&lt;span style="font-family: inherit; font-size: large;"&gt;కథ - సీత తల్లి&lt;/span&gt;&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-YZXR9ARJSyc/UwXCOqr5ICI/AAAAAAAAKNI/LGYl8SSiBfU/s1600/chalam-story-seetha-thalli.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-YZXR9ARJSyc/UwXCOqr5ICI/AAAAAAAAKNI/LGYl8SSiBfU/s1600/chalam-story-seetha-thalli.png" height="640" width="537"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-HjOyG6hGXfI/UwXCOvdUcyI/AAAAAAAAKNE/nPOhaJ3nalY/s1600/chalam-story-seetha-thalli2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-HjOyG6hGXfI/UwXCOvdUcyI/AAAAAAAAKNE/nPOhaJ3nalY/s1600/chalam-story-seetha-thalli2.png" height="640" width="424"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: inherit; font-size: large;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-WJ7k2JwgBIw/UwXCPPhzNBI/AAAAAAAAKNc/SPzHst_E0uk/s1600/chalam-story-seetha-thalli3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-WJ7k2JwgBIw/UwXCPPhzNBI/AAAAAAAAKNc/SPzHst_E0uk/s1600/chalam-story-seetha-thalli3.png" height="640" width="440"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-5Q56ostIeIk/UwXCN35_eVI/AAAAAAAAKNM/1LqZslhGihk/s1600/chalam-kathalu-seetha-thalli4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-5Q56ostIeIk/UwXCN35_eVI/AAAAAAAAKNM/1LqZslhGihk/s1600/chalam-kathalu-seetha-thalli4.png" height="640" width="434"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-vjfEtpw0vTo/UwXCNzU-OOI/AAAAAAAAKNA/x2McRaPjjsc/s1600/chalam-kathalu-seetha-thalli5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-vjfEtpw0vTo/UwXCNzU-OOI/AAAAAAAAKNA/x2McRaPjjsc/s1600/chalam-kathalu-seetha-thalli5.png" height="640" width="446"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-IDsq9Ytc5kA/UwXCNmUQMDI/AAAAAAAAKM4/FJ3YAjD1kto/s1600/chalam-kathalu-seetha-thalli6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-IDsq9Ytc5kA/UwXCNmUQMDI/AAAAAAAAKM4/FJ3YAjD1kto/s1600/chalam-kathalu-seetha-thalli6.png" height="160" width="400"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;More stories &amp;amp; essays.... &lt;a href="http://www.avilpage.com/2014/04/my-favorite-stories-essays-of-chalam.html"&gt;నాకు నచ్చిన చలం కథలు, వ్యాసాలు&lt;/a&gt;&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>chalam</category><guid>https://avilpage.com/2014/02/seetha-thalli-story-by-gudipati-venkatachalam.html</guid><pubDate>Thu, 20 Feb 2014 03:28:00 GMT</pubDate></item><item><title>How To Screencast Android Device Without Root?</title><link>https://avilpage.com/2014/01/how-to-easily-screencast-android-device-without-root.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;h3 style="text-align: left;"&gt;Screencasting Android Device:&lt;/h3&gt;If You want to screencast something on Anroid device, its a lot of headache. There are a few apps on Play Store by which you can screencast. But a lot of them require rooting. But if Your phone/tablet is new or if You are afraid of bricking, You don't want to root the phone.&lt;br&gt;&lt;br&gt;There are some procedures to screencast Android, but they require SDK. But You can also screencast without SDK also. This will be simplest way to screencast.&lt;br&gt;&lt;br&gt;There are only two apps on play store which offer screencasting, without rooting and without SDK.&lt;br&gt;&lt;br&gt;1. &lt;a href="https://play.google.com/store/apps/details?id=com.benzul.asc" target="_blank"&gt;ASC Screen Recorder&lt;/a&gt;&lt;br&gt;&lt;br&gt;2. &lt;a href="https://play.google.com/store/apps/details?id=uk.org.invisibility.recordablefree" target="_blank"&gt;Free Screen Recorder No Root&lt;/a&gt;&lt;br&gt;&lt;br&gt;Lets look at both of them, which is easy to install and which is easy to use!&lt;br&gt;&lt;br&gt;&lt;h3 style="text-align: left;"&gt;ASC Screen Recorder:&lt;/h3&gt;&lt;div&gt;To use ASC Screen Recorder, You NEED a PC ( must be Windows or Mac, no activator for Linux/Ubuntu ).&lt;/div&gt;&lt;div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Download app ( free or paid ) from Play Store.&lt;/li&gt;&lt;li&gt;Download &lt;a href="http://benzul.com/activator.html" target="_blank"&gt;Activator&lt;/a&gt; from here.&lt;/li&gt;&lt;li&gt;Install activator and start recording.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;With free app, you can record unlimited videos but they are restricted to only 20 seconds.  &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;Free Screen Recorder No Root:&lt;/h3&gt;&lt;div&gt;For Free Screen Recorder No Root, You can use any PC ( can be used with Ubuntu ).&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Download app ( free or paid ) from Play Store.&lt;/li&gt;&lt;li&gt;Download &lt;a href="http://recordable.mobi/install" target="_blank"&gt;Activator&lt;/a&gt; from here.&lt;/li&gt;&lt;li&gt;Install activator and start recording.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;You can record unlimited  videos, but their logo will be displayed on the recorded video and framerate is only upto 4fps which is not good.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;I have tested both the apps on My Samsung Core. Without root and without SDK, these are best and these are highly use for dummies!&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>android</category><guid>https://avilpage.com/2014/01/how-to-easily-screencast-android-device-without-root.html</guid><pubDate>Tue, 28 Jan 2014 22:33:00 GMT</pubDate></item><item><title>Wipro Campus Placement - My Interview!</title><link>https://avilpage.com/2014/01/avil-page-30-wipro-campus-placement.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;br&gt;

    &lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
      It happened few months back in our Sri Venkateswara University College of Engineering!&lt;br&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        First our placement officer R.V.S sent a notice about the campus placement! He arranged a session to get us prepared for campus placement. Students who
        have less than 2 backlogs were allowed to placement.
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        On the day, a few officials from Wipro came to our college. We all attended pre-placement talk in our formal dress. After the talk, they separated the
        students into two batches.
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        The first batch were the toppers who have more than 80% academic score. They don't have to take the written test and have to attend the interview
        directly.
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        I had around 78% score. So, I have to take the written test. Written test consisted of Aptitude questions and English vocabulary, passage writing. I
        was qualified in written test!
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;

        &lt;h3 style="text-align: left;"&gt;Interview:&lt;/h3&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;h3 style="text-align: left;"&gt;First round:&lt;/h3&gt;
      &lt;/div&gt;

      &lt;div&gt;
        I entered into the cell greeted the interviewer. He asked me to sit down. He spoke politely and asked a few questions casually to make me comfortable.
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;h3 style="text-align: left;"&gt;Second round:&lt;/h3&gt;

      &lt;div&gt;
        In this round, the interviewer asked me about the Android app I have developed. I told that it was very basic app and told him how I developed it. He spoke a lot about Andoid apps and asked me to participate in App contest help by Wipro.
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        That's it. My interview was completed. Later I went out for a walk!
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        On return one of my friend told me that I got selected!
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;

      &lt;div&gt;
        &lt;br&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;</description><category>interview</category><guid>https://avilpage.com/2014/01/avil-page-30-wipro-campus-placement.html</guid><pubDate>Thu, 23 Jan 2014 11:22:00 GMT</pubDate></item><item><title>How I Got Into Alexa Top Million In A Few Days?</title><link>https://avilpage.com/2014/01/avil-page-29-how-to-get-in-to-alexa-top-million.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Just now ( 02:00 PM, 23 Jan 2014) I checked &lt;a href="http://www.alexa.com/" target="_blank"&gt;Alexa Rank of this blog&lt;/a&gt; and I found that it is 982,516! I just wrote a few posts and told about them to few online friends who are interested to read them. That's it!&lt;br&gt;&lt;br&gt;Here I have added complete details you needed to know about my blog! Hope that helps!&lt;br&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;Content:&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;As of today, this blog has 28 posts. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;table cellpadding="0" cellspacing="0" dir="ltr" style="font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"&gt;&lt;colgroup&gt;&lt;col width="105"&gt;&lt;col width="127"&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border: 1px solid rgb(204, 204, 204); direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;No. of Posts&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;Month&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;March 2013&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;October 2013&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;2&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;November 2013&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: right; vertical-align: bottom;"&gt;4&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;December 2013&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: right; vertical-align: bottom;"&gt;20&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;January 2014&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;h2 style="text-align: left;"&gt;Backlinks:&lt;/h2&gt;&lt;div&gt;I logged into Google webmasters and downloaded this table. I have to 15 backlinks, some of them are do follow!&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;table cellpadding="0" cellspacing="0" dir="ltr" style="font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"&gt;&lt;colgroup&gt;&lt;col width="135"&gt;&lt;col width="50"&gt;&lt;col width="64"&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border: 1px solid rgb(204, 204, 204); direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;Domains&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;Links&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;Linked pages&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://google.com&amp;amp;usd=2&amp;amp;usg=ALhdy28KajtxuQOk5nqJ_OS7fbaatJYM0g" target="_blank"&gt;google.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;43&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;8&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://youtube.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-DBWepgB2jeokI_DBPhY5Rk_iW9w" target="_blank"&gt;youtube.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;43&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;blogspot.com&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;8&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://medium.com&amp;amp;usd=2&amp;amp;usg=ALhdy29xLCajw0w55wk4TtQYZQhP1ALuNg" target="_blank"&gt;medium.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://medlibrary.org&amp;amp;usd=2&amp;amp;usg=ALhdy29Tlpr6wcua21NmYdFQYEwb4Lklrg" target="_blank"&gt;medlibrary.org&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://stumbleupon.com&amp;amp;usd=2&amp;amp;usg=ALhdy28ViNsD-fZ_Dee0uV1dmqmy310ROQ" target="_blank"&gt;stumbleupon.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://mashpedia.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-XvEj2SPerKDFzJgLJX1UCnDZEQQ" target="_blank"&gt;mashpedia.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://web-sniffer.me&amp;amp;usd=2&amp;amp;usg=ALhdy2-wrtEBsoUfuW_MbMrgymT8oNgN-A" target="_blank"&gt;web-sniffer.me&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://justclicksearch.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_TvU8RgVg9rSSSPK1Y07_SMfVT-w" target="_blank"&gt;justclicksearch.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://digplanet.com&amp;amp;usd=2&amp;amp;usg=ALhdy293I0FDjJ8P6tUKF_NFpJu0VNckDg" target="_blank"&gt;digplanet.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ency.cl&amp;amp;usd=2&amp;amp;usg=ALhdy28dE0ur6CEgfDXTRSc5mRCaNgwN2A" target="_blank"&gt;ency.cl&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://statscrop.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-O7fzkif1shRGtMIGr6HuEUedg_w" target="_blank"&gt;statscrop.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://verkata.com&amp;amp;usd=2&amp;amp;usg=ALhdy284EBDFEG7MzPseYjpxCFAlw2pL3g" target="_blank"&gt;verkata.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://goo.ne.jp&amp;amp;usd=2&amp;amp;usg=ALhdy29knvL5nEGR4FyMXwjL_zH-c_8Gpg" target="_blank"&gt;goo.ne.jp&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://wikipedia.org&amp;amp;usd=2&amp;amp;usg=ALhdy29FNLfMj_1WJn1TFwQ8WqbRPAioOA" target="_blank"&gt;wikipedia.org&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h2 style="text-align: left;"&gt;&lt;/h2&gt;&lt;h2 style="text-align: left;"&gt;&lt;/h2&gt;&lt;h2 style="text-align: left;"&gt;Stats:&lt;/h2&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-CyyufcIl1yw/UuE9PjViJRI/AAAAAAAAKLs/chE6x8m7DeY/s1600/avil-page-stats.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-CyyufcIl1yw/UuE9PjViJRI/AAAAAAAAKLs/chE6x8m7DeY/s1600/avil-page-stats.png" height="446" width="640"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>how-to</category><category>tech</category><guid>https://avilpage.com/2014/01/avil-page-29-how-to-get-in-to-alexa-top-million.html</guid><pubDate>Thu, 23 Jan 2014 10:39:00 GMT</pubDate></item><item><title>Little Alchemy Walkthrough 450 Elements Combinations!</title><link>https://avilpage.com/2014/01/little-alchemy-cheats-walkthrough-450-elements.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;h3&gt;About Little Alchemy:&lt;/h3&gt;
&lt;p&gt;Little Alchemy is a simple but addictive game. You start with four basic elements, and mix and match them to create more and more awesome things.&lt;/p&gt;
&lt;p&gt;Combine the elements by simply dragging and dropping one on the other to make something new. See how many elements you can come up with. There are 480 elements to create. &lt;/p&gt;
&lt;p&gt;&lt;a href="https://chrome.google.com/webstore/detail/little-alchemy/knkapnclbofjjgicpkfoagdjohlfjhpd?hl=en"&gt;Get Little Alchemy App for Chrome&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;&lt;a href="https://itunes.apple.com/us/app/little-alchemy/id542467126?mt=8"&gt;Get Little Alchemy App for iOS&lt;/a&gt;  &lt;/p&gt;
&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.sometimeswefly.littlealchemy"&gt;Get Little Alchemy App for Android&lt;/a&gt;  &lt;/p&gt;
&lt;h3&gt;Little Alchemy Walkthrough:&lt;/h3&gt;
&lt;p&gt;I have recorded a few videos for few elements.&lt;/p&gt;
&lt;p&gt;Little Alchemy Walkthrough First 20 Elements - Part 1!&lt;/p&gt;
&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/CabQOGEOPyc" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Little Alchemy Walkthrough First 20 Elements - Part 2!&lt;/p&gt;
&lt;div class="embed-responsive embed-responsive-16by9"&gt;
&lt;iframe class="embed-responsive-item" src="https://www.youtube.com/embed/WB4HKhRgqSU" allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;Little Alchemy All Cheats&lt;/h3&gt;
&lt;p&gt;You can make 450 elements with the four basic elements. Here is the complete solutions for Little Alchemy!&lt;/p&gt;
&lt;p&gt;1. Water&lt;/p&gt;
&lt;p&gt;2. Fire&lt;/p&gt;
&lt;p&gt;3. Earth&lt;/p&gt;
&lt;p&gt;4. Air&lt;/p&gt;
&lt;p&gt;5. Acid rain = rain + smoke&lt;/p&gt;
&lt;p&gt;6. Airplane = metal + bird, steel + bird&lt;/p&gt;
&lt;p&gt;7. Alarm clock = clock + sound&lt;/p&gt;
&lt;p&gt;8. Alcohol = time + fruit, juice + time&lt;/p&gt;
&lt;p&gt;9. Algae = plant + ocean, plant + water, plant + sea&lt;/p&gt;
&lt;p&gt;10. Alien = life + space&lt;/p&gt;
&lt;p&gt;11. Allergy = dust + human&lt;/p&gt;
&lt;p&gt;12. Alligator = swamp + lizard&lt;/p&gt;
&lt;p&gt;13. Ambulance = car + hospital, car + doctor&lt;/p&gt;
&lt;p&gt;14. Angel = bird + human&lt;/p&gt;
&lt;p&gt;15. Antarctica = desert + ice, desert + snow&lt;/p&gt;
&lt;p&gt;16. Aquarium = water + glass, glass + fish&lt;/p&gt;
&lt;p&gt;17. Archipelago = isle + isle&lt;/p&gt;
&lt;p&gt;18. Armadillo = wild animal + armor&lt;/p&gt;
&lt;p&gt;19. Armor = metal + tool, steel + tool&lt;/p&gt;
&lt;p&gt;20. Ash = energy + volcano&lt;/p&gt;
&lt;p&gt;21. Astronaut = human + moon, rocket + human, human + spacestation&lt;/p&gt;
&lt;p&gt;22. Atmosphere = air + pressure, sky + pressure&lt;/p&gt;
&lt;p&gt;23. Atomic bomb = energy + explosion&lt;/p&gt;
&lt;p&gt;24. Avalanche = energy + snow&lt;/p&gt;
&lt;p&gt;25. Axe= blade + wood&lt;/p&gt;
&lt;p&gt;26. Bacon = fire + pig&lt;/p&gt;
&lt;p&gt;27. Bacteria = swamp + life&lt;/p&gt;
&lt;p&gt;28. Baker = human + bread, human + flour&lt;/p&gt;
&lt;p&gt;29. Banana = monkey + fruit&lt;/p&gt;
&lt;p&gt;30. Bank = house + gold, house + money&lt;/p&gt;
&lt;p&gt;31. Barn = house + cow, house + livestock&lt;/p&gt;
&lt;p&gt;32. Bat = mouse + bird, sky + mouse&lt;/p&gt;
&lt;p&gt;33. Batter = flour + milk&lt;/p&gt;
&lt;p&gt;34. Batman = bat + human&lt;/p&gt;
&lt;p&gt;35. Bayonet = blade + gun&lt;/p&gt;
&lt;p&gt;36. Beach = water + sand, sand + ocean, sand + sea&lt;/p&gt;
&lt;p&gt;37. Beaver = wild animal + wood&lt;/p&gt;
&lt;p&gt;38. Bee = flower + wild animal&lt;/p&gt;
&lt;p&gt;39. Beehive = house + bee, tree + bee&lt;/p&gt;
&lt;p&gt;40. Beer = alcohol + wheat&lt;/p&gt;
&lt;p&gt;41. Bicycle = wheel + wheel&lt;/p&gt;
&lt;p&gt;42. Bird = air + egg, sky + egg, sky + life&lt;/p&gt;
&lt;p&gt;43. Birdhouse = bird + house&lt;/p&gt;
&lt;p&gt;44. Black hole = star + pressure&lt;/p&gt;
&lt;p&gt;45. Blade = stone + metal&lt;/p&gt;
&lt;p&gt;46. Blizzard = snow + wind, snow + storm&lt;/p&gt;
&lt;p&gt;47. Blood = human + blade&lt;/p&gt;
&lt;p&gt;48. Boat = water + wood&lt;/p&gt;
&lt;p&gt;49. Boiler = metal + steam&lt;/p&gt;
&lt;p&gt;50. Bone = time + corpse&lt;/p&gt;
&lt;p&gt;51. Book = story + paper&lt;/p&gt;
&lt;p&gt;52. Bread = fire + dough, fire + flour&lt;/p&gt;
&lt;p&gt;53. Brick = fire + mud, fire + clay, sun + clay, sun + mud&lt;/p&gt;
&lt;p&gt;54. Bridge = steel + river, metal + river, wood + river&lt;/p&gt;
&lt;p&gt;55. Broom = hay + wood&lt;/p&gt;
&lt;p&gt;56. Bullet = gun powder + metal&lt;/p&gt;
&lt;p&gt;57. Butcher = human + meat&lt;/p&gt;
&lt;p&gt;58. Butter = pressure + milk&lt;/p&gt;
&lt;p&gt;59. Butterfly = flower + wild animal&lt;/p&gt;
&lt;p&gt;60. Cactus = desert + plant, plant + sand&lt;/p&gt;
&lt;p&gt;61. Camel = desert + horse, desert + wild animal&lt;/p&gt;
&lt;p&gt;62. Campfire = fire + wood&lt;/p&gt;
&lt;p&gt;63. Candle = fire + wax, wax + thread&lt;/p&gt;
&lt;p&gt;64. Candy cane = sugar + Christmas tree&lt;/p&gt;
&lt;p&gt;65. Car = metal + wheel&lt;/p&gt;
&lt;p&gt;66. Carbon dioxide = human + oxygen, plant + night&lt;/p&gt;
&lt;p&gt;67. Cart = wood + wheel&lt;/p&gt;
&lt;p&gt;68. Castle = knight + house&lt;/p&gt;
&lt;p&gt;69. Cat = wild animal + milk&lt;/p&gt;
&lt;p&gt;70. Catnip = plant + cat&lt;/p&gt;
&lt;p&gt;71. Caviar = human + hard roe&lt;/p&gt;
&lt;p&gt;72. Centaur = horse + human&lt;/p&gt;
&lt;p&gt;73. Cereal = milk + wheat&lt;/p&gt;
&lt;p&gt;74. Chainsaw = electricity + axe&lt;/p&gt;
&lt;p&gt;75. Chameleon = lizard + rainbow&lt;/p&gt;
&lt;p&gt;76. Charcoal = fire + wood, fire + tree&lt;/p&gt;
&lt;p&gt;77. Cheese = time + milk&lt;/p&gt;
&lt;p&gt;78. Chicken = bird + livestock&lt;/p&gt;
&lt;p&gt;79. Chimney = house + fireplace&lt;/p&gt;
&lt;p&gt;80. Christmas stocking = wool + fireplace&lt;/p&gt;
&lt;p&gt;81. Christmas tree = light bulb + tree&lt;/p&gt;
&lt;p&gt;82. Cigarette = paper + tobacco&lt;/p&gt;
&lt;p&gt;83. City = skyscraper + skyscraper, village + village&lt;/p&gt;
&lt;p&gt;84. Clay = mud + sand&lt;/p&gt;
&lt;p&gt;85. Clock = electricity + time, time + wheel&lt;/p&gt;
&lt;p&gt;86. Cloud = air + steam&lt;/p&gt;
&lt;p&gt;87. Coal = plant + pressure&lt;/p&gt;
&lt;p&gt;88. Coconut = palm + fruit&lt;/p&gt;
&lt;p&gt;89. Coconut milk = coconut + tool&lt;/p&gt;
&lt;p&gt;90. Coffin = wood + corpse&lt;/p&gt;
&lt;p&gt;91. Cold = rain + human&lt;/p&gt;
&lt;p&gt;92. Computer = electricity + nerd, nerd + tool&lt;/p&gt;
&lt;p&gt;93. Computer mouse = computer + mouse&lt;/p&gt;
&lt;p&gt;94. Confetti = paper + blade, paper + scissors&lt;/p&gt;
&lt;p&gt;95. Constellation = star + star&lt;/p&gt;
&lt;p&gt;96. Cookie = sugar + dough&lt;/p&gt;
&lt;p&gt;97. Corpse = human + gun, grim reaper + human&lt;/p&gt;
&lt;p&gt;98. Cotton = cloud + plant&lt;/p&gt;
&lt;p&gt;99. Cow = livestock + grass&lt;/p&gt;
&lt;p&gt;100. Crystal ball = glass + wizard, glass + witch&lt;/p&gt;
&lt;p&gt;101. Cuckoo = clock + bird&lt;/p&gt;
&lt;p&gt;102. Cyborg = robot + human&lt;/p&gt;
&lt;p&gt;103. Cyclist = human + bicycle&lt;/p&gt;
&lt;p&gt;104. Dam = river + wall, beaver + river, beaver + tree, beaver + wood&lt;/p&gt;
&lt;p&gt;105. Darth Vader = Jedi + lava, fire + Jedi&lt;/p&gt;
&lt;p&gt;106. Day = sun + time, sun + night&lt;/p&gt;
&lt;p&gt;107. Desert = sand + sand&lt;/p&gt;
&lt;p&gt;108. Dew = fog + grass&lt;/p&gt;
&lt;p&gt;109. Diamond = coal + pressure, coal + time&lt;/p&gt;
&lt;p&gt;110. Dinosaur = time + lizard&lt;/p&gt;
&lt;p&gt;111. Doctor = hospital + human&lt;/p&gt;
&lt;p&gt;112. Dog = wild animal + human&lt;/p&gt;
&lt;p&gt;113. Doghouse = dog + house&lt;/p&gt;
&lt;p&gt;114. Donut = dough + oil&lt;/p&gt;
&lt;p&gt;115. Double rainbow! = rainbow + rainbow&lt;/p&gt;
&lt;p&gt;116. Dough = water + flour&lt;/p&gt;
&lt;p&gt;117. Dragon = fire + lizard&lt;/p&gt;
&lt;p&gt;118. Drum = leather + wood&lt;/p&gt;
&lt;p&gt;119. Drunk = alcohol + human, beer + human&lt;/p&gt;
&lt;p&gt;120. Dry ice = cold + carbon dioxide&lt;/p&gt;
&lt;p&gt;121. Duck = water + bird&lt;/p&gt;
&lt;p&gt;122. Dune = beach + wind, desert + wind, wind + sand&lt;/p&gt;
&lt;p&gt;123. Dust = earth + air, sun + vampire&lt;/p&gt;
&lt;p&gt;124. Dynamite = wire + gunpowder&lt;/p&gt;
&lt;p&gt;125. Eagle = mountain + bird&lt;/p&gt;
&lt;p&gt;126. Earthquake = energy + earth, wave + earth&lt;/p&gt;
&lt;p&gt;127. Eclipse= sun + moon&lt;/p&gt;
&lt;p&gt;128. Egg = stone + life, bird + bird, lizard + lizard, turtle + turtle&lt;/p&gt;
&lt;p&gt;129. Egg timer = clock + egg&lt;/p&gt;
&lt;p&gt;130. Electric car = car + electricity&lt;/p&gt;
&lt;p&gt;131. Electric eel = electricity + fish&lt;/p&gt;
&lt;p&gt;132. Electrician = electricity + human, electricity + flashlight&lt;/p&gt;
&lt;p&gt;133. Electricity = energy + metal, sun + solar cell, wind + wind turbine&lt;/p&gt;
&lt;p&gt;134. Email = computer + letter&lt;/p&gt;
&lt;p&gt;135. Energy = fire + air, sun + plant&lt;/p&gt;
&lt;p&gt;136. Engineer = human + tool&lt;/p&gt;
&lt;p&gt;137. Eruption = energy + volcano&lt;/p&gt;
&lt;p&gt;138. Excalibur = stone + sword&lt;/p&gt;
&lt;p&gt;139. Explosion = fire + gunpowder&lt;/p&gt;
&lt;p&gt;140. Fabric = thread + tool&lt;/p&gt;
&lt;p&gt;141. Family = human + house&lt;/p&gt;
&lt;p&gt;142. Farmer = human + field, plant + human&lt;/p&gt;
&lt;p&gt;143. Faun = goat + human&lt;/p&gt;
&lt;p&gt;144. Fence = wall + wood&lt;/p&gt;
&lt;p&gt;145. Field = earth + tool&lt;/p&gt;
&lt;p&gt;146. Fireman = fire + human&lt;/p&gt;
&lt;p&gt;147. Fireplace = campfire + house&lt;/p&gt;
&lt;p&gt;148. Fire truck = fireman + car&lt;/p&gt;
&lt;p&gt;149. Fireworks = sky + explosion&lt;/p&gt;
&lt;p&gt;150. Fish = time + hard roe&lt;/p&gt;
&lt;p&gt;151. Fishing rod = tool + fish, wood + fish&lt;/p&gt;
&lt;p&gt;152. Flashlight = light + tool&lt;/p&gt;
&lt;p&gt;153. Flood = rain + time, rain + rain&lt;/p&gt;
&lt;p&gt;154. Flour = stone + wheat, windmill + wheat&lt;/p&gt;
&lt;p&gt;155. Flower = plant + garden&lt;/p&gt;
&lt;p&gt;156. Flute = wind + wood&lt;/p&gt;
&lt;p&gt;157. Flying fish = fish + bird&lt;/p&gt;
&lt;p&gt;158. Flying squirrel = squirrel + bird, squirrel + wind, squirrel + airplane&lt;/p&gt;
&lt;p&gt;159. Fog = cloud + earth&lt;/p&gt;
&lt;p&gt;160. Forest = tree + tree&lt;/p&gt;
&lt;p&gt;161. Fossil = dinosaur + earth, dinosaur + time&lt;/p&gt;
&lt;p&gt;162. Fountain = statue + water&lt;/p&gt;
&lt;p&gt;163. Fox = chicken + wild animal&lt;/p&gt;
&lt;p&gt;164. Frankenstein = electricity + corpse, electricity + zombie&lt;/p&gt;
&lt;p&gt;165. Fridge = cold + metal, cold + electricity&lt;/p&gt;
&lt;p&gt;166. Fruit = tree + farmer, sun + tree&lt;/p&gt;
&lt;p&gt;167. Fruit tree = tree + fruit&lt;/p&gt;
&lt;p&gt;168. Galaxy = star + star&lt;/p&gt;
&lt;p&gt;169. Garden = plant + grass, plant + plant&lt;/p&gt;
&lt;p&gt;170. Geyser = earth + steam&lt;/p&gt;
&lt;p&gt;171. Ghost = graveyard + night, castle + night&lt;/p&gt;
&lt;p&gt;172. Gift = Santa + Christmas tree, Santa + chimney, fireplace + Santa, Santa + Christmas stocking, Santa + cookies&lt;/p&gt;
&lt;p&gt;173. Glacier = ice + mountain&lt;/p&gt;
&lt;p&gt;174. Glass = fire + sand, electricity + sand&lt;/p&gt;
&lt;p&gt;175. Glasses = glass + glass, glass + metal&lt;/p&gt;
&lt;p&gt;176. Glasshouse = plant + glass&lt;/p&gt;
&lt;p&gt;177. Goat = mountain + livestock&lt;/p&gt;
&lt;p&gt;178. Gold = sun + metal&lt;/p&gt;
&lt;p&gt;179. Golem = life + clay&lt;/p&gt;
&lt;p&gt;180. Grass = earth + plant&lt;/p&gt;
&lt;p&gt;181. Grave = earth + coffin, earth + corpse&lt;/p&gt;
&lt;p&gt;182. Gravestone = stone + grave&lt;/p&gt;
&lt;p&gt;183. Graveyard = grave + grave&lt;/p&gt;
&lt;p&gt;184. Grenade = explosion + metal&lt;/p&gt;
&lt;p&gt;185. Grim reaper = scythe + corpse, scythe + human&lt;/p&gt;
&lt;p&gt;186. Gun = metal + bullet&lt;/p&gt;
&lt;p&gt;187. Gunpowder = fire + dust&lt;/p&gt;
&lt;p&gt;188. Hail = cloud + ice, ice + storm, rain + ice&lt;/p&gt;
&lt;p&gt;189. Ham = meat + smoke&lt;/p&gt;
&lt;p&gt;190. Hamburger = bread + meat&lt;/p&gt;
&lt;p&gt;191. Hard roe = water + egg, egg + ocean, egg + sea, fish + fish&lt;/p&gt;
&lt;p&gt;192. Hay = farmer + grass, scythe + grass&lt;/p&gt;
&lt;p&gt;193. Helicopter = blade + airplane&lt;/p&gt;
&lt;p&gt;194. Hero = dragon + knight&lt;/p&gt;
&lt;p&gt;195. Hippo = horse + river, horse + water&lt;/p&gt;
&lt;p&gt;196. Honey = bee + flower&lt;/p&gt;
&lt;p&gt;197. Horizon = earth + sky, sky + ocean, sky + sea&lt;/p&gt;
&lt;p&gt;198. Horse = hay + livestock&lt;/p&gt;
&lt;p&gt;199. Hospital = sickness + house&lt;/p&gt;
&lt;p&gt;200. Hourglass = sand + glass&lt;/p&gt;
&lt;p&gt;201. House = brick + tool, human + wood, brick + human, wall + wall&lt;/p&gt;
&lt;p&gt;202. Human = earth + life&lt;/p&gt;
&lt;p&gt;203. Hummingbird = bird + flower&lt;/p&gt;
&lt;p&gt;204. Hurricane = energy + wind&lt;/p&gt;
&lt;p&gt;205. Ice = water + cold&lt;/p&gt;
&lt;p&gt;206. Ice cream = cold + milk, ice + milk&lt;/p&gt;
&lt;p&gt;207. Iceberg = Antarctica + ocean, Antarctica + sea, ice + ocean, ice + sea&lt;/p&gt;
&lt;p&gt;208. Idea = light bulb + human&lt;/p&gt;
&lt;p&gt;209. Igloo = ice + house&lt;/p&gt;
&lt;p&gt;210. Internet = computer + computer, wire + computer&lt;/p&gt;
&lt;p&gt;211. Isle = volcano + ocean&lt;/p&gt;
&lt;p&gt;212. Jack-o-lantern = pumpkin + fire&lt;/p&gt;
&lt;p&gt;213. Jedi = light saber + human, knight + light saber&lt;/p&gt;
&lt;p&gt;214. Juice = water + fruit, pressure + fruit&lt;/p&gt;
&lt;p&gt;215. Kite = wind + paper&lt;/p&gt;
&lt;p&gt;216. King = human + castle, human + Excalibur&lt;/p&gt;
&lt;p&gt;217. Knight = armor + human&lt;/p&gt;
&lt;p&gt;218. Lamp = light bulb + metal&lt;/p&gt;
&lt;p&gt;219. Lava = fire + earth&lt;/p&gt;
&lt;p&gt;220. Lava lamp = lamp + lava&lt;/p&gt;
&lt;p&gt;221. Lawn mower = grass + tool&lt;/p&gt;
&lt;p&gt;222. Leaf = tree + wind&lt;/p&gt;
&lt;p&gt;223. Leather = blade + cow, pig + blade&lt;/p&gt;
&lt;p&gt;224. Lemonade = water + fruit&lt;/p&gt;
&lt;p&gt;225. Letter = paper + pencil&lt;/p&gt;
&lt;p&gt;226. Life = energy + swamp, time + love&lt;/p&gt;
&lt;p&gt;227. Light = electricity + light bulb&lt;/p&gt;
&lt;p&gt;228. Light bulb = electricity + glass&lt;/p&gt;
&lt;p&gt;229. Lighthouse = light + ocean, light + sea, beach + light, light + house&lt;/p&gt;
&lt;p&gt;230. Light saber = light + sword, electricity + sword, energy + sword&lt;/p&gt;
&lt;p&gt;231. Lion = wild animal + cat&lt;/p&gt;
&lt;p&gt;232. Livestock = wild animal + human, life + farmer&lt;/p&gt;
&lt;p&gt;233. Lizard = swamp + egg&lt;/p&gt;
&lt;p&gt;234. Love = human + human&lt;/p&gt;
&lt;p&gt;235. Lumberjack = human + axe&lt;/p&gt;
&lt;p&gt;236. Map = paper + earth&lt;/p&gt;
&lt;p&gt;237. Manatee = cow + sea&lt;/p&gt;
&lt;p&gt;238. Marshmallows = sugar + campfire&lt;/p&gt;
&lt;p&gt;239. Mayonnaise = egg + oil&lt;/p&gt;
&lt;p&gt;240. Meat = tool + cow, pig + tool&lt;/p&gt;
&lt;p&gt;241. Medusa = human + snake&lt;/p&gt;
&lt;p&gt;242. Mermaid = human + fish&lt;/p&gt;
&lt;p&gt;243. Metal = fire + stone&lt;/p&gt;
&lt;p&gt;244. Meteor = atmosphere + meteoroid&lt;/p&gt;
&lt;p&gt;245. Meteoroid = space + stone&lt;/p&gt;
&lt;p&gt;246. Milk = human + cow, farmer + cow&lt;/p&gt;
&lt;p&gt;247. Milk shake = milk + ice cream&lt;/p&gt;
&lt;p&gt;248. Minotaur = cow + human&lt;/p&gt;
&lt;p&gt;249. Mirror = glass + metal&lt;/p&gt;
&lt;p&gt;250. Money = paper + gold&lt;/p&gt;
&lt;p&gt;251. Monkey = wild animal + tree&lt;/p&gt;
&lt;p&gt;252. Moon = sky + cheese&lt;/p&gt;
&lt;p&gt;253. Moss = algae + stone, plant + stone&lt;/p&gt;
&lt;p&gt;254. Motorcycle = energy + bicycle, steel + bicycle&lt;/p&gt;
&lt;p&gt;255. Mountain = earthquake + earth&lt;/p&gt;
&lt;p&gt;256. Mouse = wild animal + cheese&lt;/p&gt;
&lt;p&gt;257. Mousetrap = wood + cheese, metal + cheese&lt;/p&gt;
&lt;p&gt;258. Mud = water + earth&lt;/p&gt;
&lt;p&gt;259. Mummy = pyramid + corpse&lt;/p&gt;
&lt;p&gt;260. Music = flute + human, sound + human&lt;/p&gt;
&lt;p&gt;261. Narwhal = water + unicorn, ocean + unicorn&lt;/p&gt;
&lt;p&gt;262. Needle = hay + metal, metal + thread&lt;/p&gt;
&lt;p&gt;263. Nerd = glasses + human&lt;/p&gt;
&lt;p&gt;264. Nest = hay + bird, tree + bird&lt;/p&gt;
&lt;p&gt;265. Newspaper = paper + paper&lt;/p&gt;
&lt;p&gt;266. Night = time + moon&lt;/p&gt;
&lt;p&gt;267. Ninja = human + shuriken&lt;/p&gt;
&lt;p&gt;268. Oasis = water + desert&lt;/p&gt;
&lt;p&gt;269. Obsidian = water + lava&lt;/p&gt;
&lt;p&gt;270. Ocean = water + sea&lt;/p&gt;
&lt;p&gt;271. Oil = sunflower + pressure&lt;/p&gt;
&lt;p&gt;272. Omelette = fire + egg&lt;/p&gt;
&lt;p&gt;273. Orchard = fruit tree + fruit tree&lt;/p&gt;
&lt;p&gt;274. Origami = paper + bird&lt;/p&gt;
&lt;p&gt;275. Ostrich = sand + bird, earth + bird&lt;/p&gt;
&lt;p&gt;276. Owl = night + bird&lt;/p&gt;
&lt;p&gt;277. Oxygen = sun + plant&lt;/p&gt;
&lt;p&gt;278. Palm = isle + tree&lt;/p&gt;
&lt;p&gt;279. Paper = wood + pressure&lt;/p&gt;
&lt;p&gt;280. Paper airplane = airplane + paper&lt;/p&gt;
&lt;p&gt;281. Parrot = pirate + bird&lt;/p&gt;
&lt;p&gt;282. Pasta = egg + flour&lt;/p&gt;
&lt;p&gt;283. Peacock = bird + rainbow&lt;/p&gt;
&lt;p&gt;284. Pegasus = horse + bird, horse + sky&lt;/p&gt;
&lt;p&gt;285. Pencil = charcoal + wood, coal + wood&lt;/p&gt;
&lt;p&gt;286. Penguin = wild animal + ice, ice + bird&lt;/p&gt;
&lt;p&gt;287. Petroleum = fossil + pressure, fossil + time&lt;/p&gt;
&lt;p&gt;288. Phoenix = fire + bird&lt;/p&gt;
&lt;p&gt;289. Picnic = grass + sandwich, beach + sandwich&lt;/p&gt;
&lt;p&gt;290. Pie = dough + fruit&lt;/p&gt;
&lt;p&gt;291. Pig = mud + livestock&lt;/p&gt;
&lt;p&gt;292. Pigeon = bird + statue, bird + city, bird + letter&lt;/p&gt;
&lt;p&gt;293. Piggy bank = pig + money&lt;/p&gt;
&lt;p&gt;294. Pilot = airplane + human, seaplane + human&lt;/p&gt;
&lt;p&gt;295. Pinocchio = life + wood&lt;/p&gt;
&lt;p&gt;296. Pipe = wood + tobacco&lt;/p&gt;
&lt;p&gt;297. Piranha = blood + fish&lt;/p&gt;
&lt;p&gt;298. Pirate = sword + sailor&lt;/p&gt;
&lt;p&gt;299. Pirate ship = pirate + boat&lt;/p&gt;
&lt;p&gt;300. Pizza = cheese + dough&lt;/p&gt;
&lt;p&gt;301. Planet = earth + space&lt;/p&gt;
&lt;p&gt;302. Plankton = water + life&lt;/p&gt;
&lt;p&gt;303. Plant = rain + earth&lt;/p&gt;
&lt;p&gt;304. Platypus = beaver + duck&lt;/p&gt;
&lt;p&gt;305. Pond = water + garden&lt;/p&gt;
&lt;p&gt;306. Popsicle = ice + juice&lt;/p&gt;
&lt;p&gt;307. Pottery = fire + clay&lt;/p&gt;
&lt;p&gt;308. Pressure = earth + earth, air + air&lt;/p&gt;
&lt;p&gt;309. Printer = paper + computer&lt;/p&gt;
&lt;p&gt;310. Prism = rainbow + glass&lt;/p&gt;
&lt;p&gt;311. Pumpkin = vegetable + fire, vegetable + light&lt;/p&gt;
&lt;p&gt;312. Pyramid = desert + grave&lt;/p&gt;
&lt;p&gt;313. Rain = water + air, water + cloud&lt;/p&gt;
&lt;p&gt;314. Rainbow = sun + rain&lt;/p&gt;
&lt;p&gt;315. Reindeer = wild animal + Santa&lt;/p&gt;
&lt;p&gt;316. Ring = diamond + metal, diamond + gold&lt;/p&gt;
&lt;p&gt;317. River = water + mountain&lt;/p&gt;
&lt;p&gt;318. Robot = metal + life, steel + life&lt;/p&gt;
&lt;p&gt;319. Rocket = airplane + space&lt;/p&gt;
&lt;p&gt;320. Rose = flower + love, plant + love&lt;/p&gt;
&lt;p&gt;321. Rust = air + metal, metal + oxygen&lt;/p&gt;
&lt;p&gt;322. Saddle = leather + horse&lt;/p&gt;
&lt;p&gt;323. Sailboat = wind + boat&lt;/p&gt;
&lt;p&gt;324. Sailor = sailboat + human, human + boat&lt;/p&gt;
&lt;p&gt;325. Salt = sun + ocean, sun + sea&lt;/p&gt;
&lt;p&gt;326. Sand = stone + air&lt;/p&gt;
&lt;p&gt;327. Sandcastle = sand + castle&lt;/p&gt;
&lt;p&gt;328. Sandpaper = paper + sand&lt;/p&gt;
&lt;p&gt;329. Sandstone = stone + sand&lt;/p&gt;
&lt;p&gt;330. Sandstorm = hurricane + sand, energy + sand, storm + sand&lt;/p&gt;
&lt;p&gt;331. Sandwich = cheese + bread, bread + ham&lt;/p&gt;
&lt;p&gt;332. Santa = human + Christmas tree&lt;/p&gt;
&lt;p&gt;333. Scalpel = doctor + blade&lt;/p&gt;
&lt;p&gt;334. Scarecrow = human + hay&lt;/p&gt;
&lt;p&gt;335. Scissors = blade + blade&lt;/p&gt;
&lt;p&gt;336. Scorpion = wild animal + sand, wild animal + dune&lt;/p&gt;
&lt;p&gt;337. Scythe = blade + grass, blade + wheat&lt;/p&gt;
&lt;p&gt;338. Sea = water + water&lt;/p&gt;
&lt;p&gt;339. Seagull = beach + bird, bird + ocean, bird + sea&lt;/p&gt;
&lt;p&gt;340. Seahorse = horse + ocean, horse + sea&lt;/p&gt;
&lt;p&gt;341. Seal = dog + sea&lt;/p&gt;
&lt;p&gt;342. Seaplane = water + airplane, sea + airplane, ocean + airplane&lt;/p&gt;
&lt;p&gt;343. Seasickness = sickness + ocean, sickness + sea&lt;/p&gt;
&lt;p&gt;344. Seaweed = plant + ocean, plant + sea&lt;/p&gt;
&lt;p&gt;345. Shark = blood + ocean, blood + sea, wild animal + ocean, wild animal + sea&lt;/p&gt;
&lt;p&gt;346. Sheep = cloud + livestock&lt;/p&gt;
&lt;p&gt;347. Sheet music = music + paper&lt;/p&gt;
&lt;p&gt;348. Shuriken = star + blade&lt;/p&gt;
&lt;p&gt;349. Sickness = rain + human, sickness + human&lt;/p&gt;
&lt;p&gt;350. Skateboard = snowboard + wheel&lt;/p&gt;
&lt;p&gt;351. Skeleton = corpse + time, bone + bone&lt;/p&gt;
&lt;p&gt;352. Ski goggles = snow + glasses&lt;/p&gt;
&lt;p&gt;353. Sky = cloud + air&lt;/p&gt;
&lt;p&gt;354. Skyscraper = sky + house&lt;/p&gt;
&lt;p&gt;355. Sledge = snow + wagon, snow + cart&lt;/p&gt;
&lt;p&gt;356. Sloth = wild animal + time&lt;/p&gt;
&lt;p&gt;357. Smog = fog + smoke&lt;/p&gt;
&lt;p&gt;358. Smoke = fire + wood&lt;/p&gt;
&lt;p&gt;359. Snake = wire + wild animal&lt;/p&gt;
&lt;p&gt;360. Snow = rain + cold&lt;/p&gt;
&lt;p&gt;361. Snowball = snow + human&lt;/p&gt;
&lt;p&gt;362. Snowboard = snow + wood&lt;/p&gt;
&lt;p&gt;363. Snowman = snow + human&lt;/p&gt;
&lt;p&gt;364. Snowmobile = cold + car, snow + motorcycle&lt;/p&gt;
&lt;p&gt;365. Soap = ash + oil&lt;/p&gt;
&lt;p&gt;366. Solar cell = sun + tool&lt;/p&gt;
&lt;p&gt;367. Solar system = sun + planet&lt;/p&gt;
&lt;p&gt;368. Sound = wave + air&lt;/p&gt;
&lt;p&gt;369. Space = star + moon, star + sky, sun + star&lt;/p&gt;
&lt;p&gt;370. Space station = house + space&lt;/p&gt;
&lt;p&gt;371. Spider = thread + wild animal&lt;/p&gt;
&lt;p&gt;372. Squirrel = mouse + tree&lt;/p&gt;
&lt;p&gt;373. Star = night + sky&lt;/p&gt;
&lt;p&gt;374. Starfish = star + fish, star + ocean, star + sea&lt;/p&gt;
&lt;p&gt;375. Statue = stone + tool&lt;/p&gt;
&lt;p&gt;376. Steam = water + fire, water + energy&lt;/p&gt;
&lt;p&gt;377. Steam engine = boiler + tool&lt;/p&gt;
&lt;p&gt;378. Steamboat = steam engine + boat, water + steam engine&lt;/p&gt;
&lt;p&gt;379. Steel = coal + metal&lt;/p&gt;
&lt;p&gt;380. Stone = air + lava&lt;/p&gt;
&lt;p&gt;381. Storm = electricity + cloud, energy + cloud&lt;/p&gt;
&lt;p&gt;382. Story = human + campfire&lt;/p&gt;
&lt;p&gt;383. Sugar = fire + juice, energy + fruit, energy + juice&lt;/p&gt;
&lt;p&gt;384. Sun = fire + sky&lt;/p&gt;
&lt;p&gt;385. Sundial = sun + clock&lt;/p&gt;
&lt;p&gt;386. Sunflower = sun + plant, sun + flower&lt;/p&gt;
&lt;p&gt;387. Sunglasses = sun + glasses&lt;/p&gt;
&lt;p&gt;388. Surfer = wave + human&lt;/p&gt;
&lt;p&gt;389. Sushi = seaweed + caviar, seaweed + fish&lt;/p&gt;
&lt;p&gt;390. Swamp = mud + plant&lt;/p&gt;
&lt;p&gt;391. Sweater = wool + tool&lt;/p&gt;
&lt;p&gt;392. Swim goggles = water + glasses&lt;/p&gt;
&lt;p&gt;393. Sword = metal + blade, steel + blade&lt;/p&gt;
&lt;p&gt;394. Swordfish = sword + fish&lt;/p&gt;
&lt;p&gt;395. Tank = armor + car, car + gun&lt;/p&gt;
&lt;p&gt;396. Tea = water + leaf&lt;/p&gt;
&lt;p&gt;397. Telescope =star +glass, sky + glass&lt;/p&gt;
&lt;p&gt;398. Thread = cotton + tool&lt;/p&gt;
&lt;p&gt;399. Tide = moon + ocean, moon + sea&lt;/p&gt;
&lt;p&gt;400. Time = sand + glass&lt;/p&gt;
&lt;p&gt;401. Titanic = iceberg + steamboat&lt;/p&gt;
&lt;p&gt;402. Toast = fire + bread, fire + sandwich&lt;/p&gt;
&lt;p&gt;403. Tobacco = fire + plant&lt;/p&gt;
&lt;p&gt;404. Tool = metal + human&lt;/p&gt;
&lt;p&gt;405. Train = metal + steam engine, steel + steam engine&lt;/p&gt;
&lt;p&gt;406. Tree = plant + time&lt;/p&gt;
&lt;p&gt;407. Treehouse = tree + house&lt;/p&gt;
&lt;p&gt;408. Trojan horse = horse + wood&lt;/p&gt;
&lt;p&gt;409. Tsunami = earthquake + ocean&lt;/p&gt;
&lt;p&gt;410. Turtle = sand + egg&lt;/p&gt;
&lt;p&gt;411. Twilight = day + night&lt;/p&gt;
&lt;p&gt;412. Umbrella = rain + tool&lt;/p&gt;
&lt;p&gt;413. Unicorn = double rainbow! + horse, double rainbow! + life, rainbow + horse, rainbow + life&lt;/p&gt;
&lt;p&gt;414. Vampire = blood + human, vampire + human&lt;/p&gt;
&lt;p&gt;415. Vase = plant + pottery&lt;/p&gt;
&lt;p&gt;416. Vegetable = fruit + field&lt;/p&gt;
&lt;p&gt;417. Village = house + house&lt;/p&gt;
&lt;p&gt;418. Volcano = earth + lava&lt;/p&gt;
&lt;p&gt;419. Vulture = bird + corpse&lt;/p&gt;
&lt;p&gt;420. Wagon = horse + cart&lt;/p&gt;
&lt;p&gt;421. Wall = brick + brick&lt;/p&gt;
&lt;p&gt;422. Wand = wizard + wood&lt;/p&gt;
&lt;p&gt;423. Warrior = sword + human&lt;/p&gt;
&lt;p&gt;424. Watch = clock + human&lt;/p&gt;
&lt;p&gt;425. Water gun = water + gun&lt;/p&gt;
&lt;p&gt;426. Water lilly = flower + pond&lt;/p&gt;
&lt;p&gt;427. Water pipe = water + pipe&lt;/p&gt;
&lt;p&gt;428. Wave = wind + ocean, wind + sea&lt;/p&gt;
&lt;p&gt;429. Wax = bee + beehive&lt;/p&gt;
&lt;p&gt;430. Web = spider + thread&lt;/p&gt;
&lt;p&gt;431. Werewolf = wolf + human, werewolf + human&lt;/p&gt;
&lt;p&gt;432. Wheat = field + farmer&lt;/p&gt;
&lt;p&gt;433. Wheel = tool + wood&lt;/p&gt;
&lt;p&gt;434. Wild animal = life + forest&lt;/p&gt;
&lt;p&gt;435. Wild boar = wild animal + pig, pig + forest&lt;/p&gt;
&lt;p&gt;436. Wind = air + pressure&lt;/p&gt;
&lt;p&gt;437. Wind turbine = electricity + windmill&lt;/p&gt;
&lt;p&gt;438. Windmill = wind + house, wind + wheel&lt;/p&gt;
&lt;p&gt;439. Wine = alcohol + fruit&lt;/p&gt;
&lt;p&gt;440. Wire = electricity + metal&lt;/p&gt;
&lt;p&gt;441. Witch = broom + wizard&lt;/p&gt;
&lt;p&gt;442. Wizard = energy + human&lt;/p&gt;
&lt;p&gt;443. Wolf = dog + forest, wild animal + dog, wild animal + moon&lt;/p&gt;
&lt;p&gt;444. Wood = tree + tool&lt;/p&gt;
&lt;p&gt;445. Woodpecker = bird + wood&lt;/p&gt;
&lt;p&gt;446. Wool = sheep + tool&lt;/p&gt;
&lt;p&gt;447. Wrapping paper = gift + paper&lt;/p&gt;
&lt;p&gt;448. Yoda = Jedi + swamp&lt;/p&gt;
&lt;p&gt;449. Yogurt = bacteria + milk&lt;/p&gt;
&lt;p&gt;450. Zombie = life + corpse, human + zombie&lt;/p&gt;</description><category>gaming</category><category>little-alchemy</category><guid>https://avilpage.com/2014/01/little-alchemy-cheats-walkthrough-450-elements.html</guid><pubDate>Tue, 21 Jan 2014 03:14:00 GMT</pubDate></item><item><title>Chrome Web App Pathuku Walk through All Levels!</title><link>https://avilpage.com/2014/01/chrome-web-app-pathuku-walkthrough-all-levels.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;As few of You know I have solved a lot of Unblock Me puzzles and posted cheats at &lt;a href="http://www.unblockmesolutions.com/" target="_blank"&gt;Unblock Me Solutions&lt;/a&gt;.&lt;br&gt;&lt;br&gt;From the past few months I haven't playing any games or puzzles. But just now I stumbled on this interesting and addictive chrome web app Pathuku!&lt;br&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;Pathuku - Connecting The Lines!&lt;/h2&gt;&lt;div&gt;It is much interesting for me and started solving a few of them. It is extremely simple and extremely tricky too! You can add &lt;a href="https://chrome.google.com/webstore/detail/pathuku/hkiilmogcdkeefnbemdagpmcediekadb" target="_blank"&gt;this puzzle&lt;/a&gt; to Your chrome browser and you can play yourself for a few minutes.&lt;br&gt;&lt;br&gt;I have added a few cheats that I have recorded. Check out my Youtube playlist &lt;a href="https://www.youtube.com/playlist?list=PLmpOFd2eNSCgCa7_qJLQ77WhQnt3O05u4" target="_blank"&gt;Pathuku Walkthrough&lt;/a&gt; for more cheats!&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/vjaRrtmii0M/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/vjaRrtmii0M?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/vjaRrtmii0M?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/wjkOSZHiPe4/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/wjkOSZHiPe4?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/wjkOSZHiPe4?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/0AAUuhWu8fA/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/0AAUuhWu8fA?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/0AAUuhWu8fA?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/zdsJFbteDns/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/zdsJFbteDns?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/zdsJFbteDns?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/ruKHQQYvfos/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/ruKHQQYvfos?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/ruKHQQYvfos?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/5PVLKYiXVuw/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/5PVLKYiXVuw?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/5PVLKYiXVuw?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/z3dQb48ZHy0/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/z3dQb48ZHy0?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/z3dQb48ZHy0?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://ytimg.googleusercontent.com/vi/ZZZgnYLB88M/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="https://www.youtube.com/v/ZZZgnYLB88M?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed width="700" height="400" src="https://www.youtube.com/v/ZZZgnYLB88M?version=3&amp;amp;f=user_uploads&amp;amp;c=google-webdrive-0&amp;amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>gaming</category><guid>https://avilpage.com/2014/01/chrome-web-app-pathuku-walkthrough-all-levels.html</guid><pubDate>Thu, 16 Jan 2014 11:46:00 GMT</pubDate></item><item><title>నాకు తెలిసిన చలం! (The Chalam, I Know)</title><link>https://avilpage.com/2014/01/chalam-i-know.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
    &lt;div style="background-color: white; color: #414141; line-height: 19.1875px; padding: 0px 0px 18px;"&gt;
      &lt;span style="font-family: inherit;"&gt;గొప్పగా అలోచించే వాళ్ళలో ఓ రకమైన విశ్రుంఖలత్వం వుంటుంది. వీళ్ళు ముఖ్యంగా మన సనాతన ధర్మాలని ప్రశ్నిస్తారు. కానీ వీళ్ళ
      వాక్పటిమ ఎంతగా వుంటుందంటే, వీళ్ళు మన ఆచారాలను ప్రశ్నించినా అందులో ఏదో నిజం ఉందనుకుంటాం. ఇలాంటివాళ్ళు వితండవాదం చేసినా అది అభ్యుదయ భావాలుగల వాళ్ళకు
      నచ్చుతుంది. కానీ వీళ్ళని సాంప్రదాయవాదులు వ్యతిరేకిస్తారు, సరైన కారణం లేకపోయినా, ఎందుకంటే వీళ్ళ తర్కానికి వాళ్ళు సమాధానం చెప్పలేరు. ఈ అభ్యుదయ భావాలు గల
      వాళ్ళు (వీళ్ళలో ఓ వర్గమే ఈ హేతువాదులు) ఇలాంటి వాళ్ళకోసమే ఎదురు చూస్తుంటారు. వీళ్ళు చెప్పేది నిజమా కాదా అని ఆలోచించరు.&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style="background-color: white; color: #414141; line-height: 19.1875px; padding: 0px 0px 18px;"&gt;
      &lt;span style="font-family: inherit;"&gt;ఇలాంటి విశ్రుంఖలత్వం ఉన్నవాళ్ళలో చలం ఒకరని నాకు అనిపించింది. నేను సుజాత అనే ఒక కథ చదివాను (చలం వ్రాసింది). సుజాత భర్త
      గొప్ప స్వాతంత్ర్యవాది(ఇది బ్రిటిష్ కాలంలో జరిగిన కథ). సుజాత భర్త ఆమెని చాలా ప్రేమగా చూసుకుంటుంటాడు. ఐనా ఆమె ఓ పోలీస్ తో అక్రమసంబంధం పెట్టుకుంటుంది.
      భర్తకి జబ్బు చేస్తుంది. అప్పుడు ఆమెకి భర్త మీడ జాలి కలుగుతుంది. భర్తకి సేవ చేస్తూ ఉంటుంది. కానీ ఈ పోలీస్ దగ్గరికి వెళ్ళడం మాత్రం మానదు. చివరగా తన తప్పు
      తెలుసుకుంటుంది (తెలుసుకున్నట్టు అనిపిస్తుంది), ఎలా అంటే నా భర్తని ఈ స్థితిలో వుండగా నీతో రాలేను అంటుంది. మళ్ళీ పోలీస్ మీదే మనసు ఉంటుంది ఆమెకు. ఇది
      మామూలుగా ఎవరైనా చెబితే ఈమె శీలం లేనిది అనే భావన కలుగుతుంది. కాని ఈ కథను చలం మలచిన తీరు చూస్తే మనకు వేరే అభిప్రాయం కలుగుతుంది. అరె ఈమె భర్తకోసం ఎంత త్యాగం
      చేసింది అని అనుకుంటాం చివరకి. ఇది చలం నైపుణ్యము.&lt;/span&gt;
    &lt;/div&gt;

    &lt;div style="background-color: white; color: #414141; line-height: 19.1875px; padding: 0px 0px 18px;"&gt;
      &lt;span style="font-family: inherit;"&gt;చలం ఆదర్శవాదులకు నచ్చుతాడు. ఎందుకంటే వీళ్ళు సామాజిక కట్టుబాట్లగురించి ఆలోచించరు. కేవలం ఆ వ్యక్తి కోణం నుంచి
      ఆలోచిస్తారు. ఈమెకి కోరిక కలిగింది కాబట్టి అతనితో వెళ్ళింది అని అనుకుంటారు. ఇక్కడ శీలం అన్న పదానికి విలువ లేదు. మనకు నచ్చింది మనం చేస్తాం అనే పద్దతిలో
      ఉంటారు. కాని కాస్త వాస్తవికతతో ఆలోచించే సాంప్రదాయవాదులు (వీళ్ళు, ఈమె తప్పుచేసింది అనే కోణంలో ఆలోచిస్తారు ) చలాన్ని వ్యతిరేకిస్తారు. ఈ గొప్పోళ్ళంతా ఏదో
      సమాజం పాడైపోయింది, మనమే దీన్ని ఉద్దరించాలి అని ఉన్న సాంప్రదాయాలకి భిన్నంగా రాస్తారు. ఇలాంటివారు కొన్ని సామాజిక కట్టుబాట్లు సహేతుకంగా లేకపొయినా, వీటిపట్ల
      వీళ్ళు మరీ అతిగా స్పందిస్తారు, పర్యవసానాలగురించి అలోచించకుండా.&lt;/span&gt;
    &lt;/div&gt;

    &lt;p&gt;Credit: &lt;a href="http://sashanka.wordpress.com/" target="_blank"&gt;శశాంక&lt;/a&gt;&lt;/p&gt;
    &lt;p style="text-align: left;"&gt;చలం కథలు&lt;/p&gt;
    &lt;a href="https://avilpage.com/2014/02/seetha-thalli-story-by-gudipati-venkatachalam.html"&gt;సీత తల్లి&lt;/a&gt;
    &lt;br&gt;
    &lt;a href="https://avilpage.com/2014/04/orey-venkatachalam-amazing-telugu-story-by-chalam.html"&gt;ఒరెయ్ వెంకటచలం!&lt;/a&gt;
  &lt;/div&gt;</description><category>chalam</category><category>telugu</category><guid>https://avilpage.com/2014/01/chalam-i-know.html</guid><pubDate>Thu, 16 Jan 2014 08:20:00 GMT</pubDate></item><item><title>Get 8 High PR Dofollow Backlinks In 8 Minutes!</title><link>https://avilpage.com/2014/01/avil-page-19-get-8-high-pr-dofollow.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I just checked my &lt;a href="http://www.quotes160.com/" target="_blank"&gt;Quotations blog &lt;/a&gt;( PR #1, Backlinks are 110 as per Google Webmasters, 30 as per Alexa )and I found the number of back links ( both do follow and no follow ) increased a lot. I added a list of sites from where I got backlinks. So lets get started.&lt;br&gt;&lt;br&gt;Assuming You can register and add a link 1 minute, You can get 8 good high quality do follow backlinks from these sites. I have already got them for my blog. You can &lt;a href="http://www.alexa.com/siteinfo/quotes160.com" target="_blank"&gt;check them on Alexa&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;h2 style="text-align: left;"&gt;List Of Sites To Get High PR Dofollow Backlinks:&lt;/h2&gt;&lt;table cellpadding="0" cellspacing="0" dir="ltr" style="font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"&gt;&lt;colgroup&gt;&lt;col width="184"&gt;&lt;col width="87"&gt;&lt;col width="471"&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border: 1px solid rgb(204, 204, 204); direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;SITE&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;PAGE RANK&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; vertical-align: bottom;"&gt;COMMENTS&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ted.com&amp;amp;usd=2&amp;amp;usg=ALhdy28vpvqBFSy3dlMw2DQM_jivozftmQ" target="_blank"&gt;ted.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;8&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Register, add Your link in profile.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://weheartit.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-wMqzB5muretzNfm2zHZMBYsFFEA" target="_blank"&gt;weheartit.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;6&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Register, add Your link in profile.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://bubblews.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_6y9C63NYRNXX5K_MKCkRjzpjhdA" target="_blank"&gt;bubblews.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;4&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Register, add Your link in profile.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://technorati.com&amp;amp;usd=2&amp;amp;usg=ALhdy29E6bxuBdo078u5MgWHGU8j_0eM7A" target="_blank"&gt;technorati.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: right; vertical-align: bottom;"&gt;7&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Register and verify Your site/blog.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://plus.google.com/&amp;amp;usd=2&amp;amp;usg=ALhdy28ISLc22xdWYCdF_xhu47DLlhmn4g" target="_blank"&gt;plus.google.com/&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: right; vertical-align: bottom;"&gt;9&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Place Your link in profile.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://youtube.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-DBWepgB2jeokI_DBPhY5Rk_iW9w" target="_blank"&gt;youtube.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: right; vertical-align: bottom;"&gt;9&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Link Your site to Your channel.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://pinterest.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_KZu_efQMn5O7F4gXAW5dtXPaZSg" target="_blank"&gt;pinterest.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: right; vertical-align: bottom;"&gt;9&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;Link Your site to Your channel, upload photos from your site.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt;&lt;br&gt;Here I have added 150+ other sites that I haven't tried!&lt;br&gt;&lt;br&gt;&lt;table cellpadding="0" cellspacing="0" dir="ltr" style="font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"&gt;&lt;colgroup&gt;&lt;col width="184"&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border: 1px solid rgb(204, 204, 204); direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://adobe.com&amp;amp;usd=2&amp;amp;usg=ALhdy29heJUPaP_ShEIKbXTnwdqtXP7TUQ" target="_blank"&gt;adobe.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://altavista.com&amp;amp;usd=2&amp;amp;usg=ALhdy28awTw-8sZMbamKu7983NWuX-jozw" target="_blank"&gt;altavista.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://amazon.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_AIKUTLiZ2nPDT1fv91s4W6hpIag" target="_blank"&gt;amazon.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://apache.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-HN3YU29Iq3j3SD9xXr1u5xzAqqA" target="_blank"&gt;apache.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://apple.com&amp;amp;usd=2&amp;amp;usg=ALhdy28vi8vyjBTZPGi6P1Fe9oRSh06V7Q" target="_blank"&gt;apple.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://berkeley.edu&amp;amp;usd=2&amp;amp;usg=ALhdy28hjjA_I4wb8VvFhfmeD20ei7cDrg" target="_blank"&gt;berkeley.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://bloglines.com&amp;amp;usd=2&amp;amp;usg=ALhdy29oXAWlt0l42GxyVt0vETargTZFuQ" target="_blank"&gt;bloglines.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cbsnews.com&amp;amp;usd=2&amp;amp;usg=ALhdy28-MGwMhBekrXfZ1YH4S8Z0yrUBkg" target="_blank"&gt;cbsnews.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cdc.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_Y8v4bV1GGKCMGfJJrx2AUhwKotQ" target="_blank"&gt;cdc.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cisco.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-afrLeDjJqJXjhHxo9XgopkaRrng" target="_blank"&gt;cisco.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cnet.com&amp;amp;usd=2&amp;amp;usg=ALhdy28JTQgz6wH_tw_AbmFHCoK5FZvvhg" target="_blank"&gt;cnet.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cnrs.fr&amp;amp;usd=2&amp;amp;usg=ALhdy2-LRS8X_Uct1_ON4B61liEPlVbZqA" target="_blank"&gt;cnrs.fr&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://com.com&amp;amp;usd=2&amp;amp;usg=ALhdy28-GhP2WX3aB0gyGlXkoPEHmLK85A" target="_blank"&gt;com.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cornell.edu&amp;amp;usd=2&amp;amp;usg=ALhdy28GzytdFwQX0TmBK-NYJ3qtM3HwwQ" target="_blank"&gt;cornell.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://creativecommons.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-jP0c7ypTXri6e6Ex4P_DokM2zow" target="_blank"&gt;creativecommons.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://dhs.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_Y_4bBHAxmz5TVcDM1YUpCcxexFw" target="_blank"&gt;dhs.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://elsevier.com&amp;amp;usd=2&amp;amp;usg=ALhdy28Y18wuw2yj2CqKJZq8qcrVgXg1Tw" target="_blank"&gt;elsevier.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://energy.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_oqBiKl4GxJm1aZo3UXuzDxwyPPw" target="_blank"&gt;energy.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://epa.gov&amp;amp;usd=2&amp;amp;usg=ALhdy29k2ud-791tzEBOYtBuSHTxNrsU4g" target="_blank"&gt;epa.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ercim.org&amp;amp;usd=2&amp;amp;usg=ALhdy29aI_XyuADUm0DozTXUijwh6jlymw" target="_blank"&gt;ercim.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ethz.ch&amp;amp;usd=2&amp;amp;usg=ALhdy2_SgGiiaeTftU59EkazWxZwAR78lg" target="_blank"&gt;ethz.ch&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ets.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-9jvFKeRlgDmhm9PZRU6RWDA6c5Q" target="_blank"&gt;ets.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://fao.org&amp;amp;usd=2&amp;amp;usg=ALhdy2_JXzhJeACRkvR0jByUTMZXppx7-g" target="_blank"&gt;fao.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://firefox.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_2r9YPZod4c8w5cVBH-VHOIPmW8Q" target="_blank"&gt;firefox.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://flash.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_excu2M7IQvVtHc4cujOBptL_Erg" target="_blank"&gt;flash.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://flickr.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_5OrVN2hwMhdRKQefewUhd1DsMPg" target="_blank"&gt;flickr.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://gamespot.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-YbTWI_T1Ni6a3lCbtBn6h53LyiQ" target="_blank"&gt;gamespot.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://grants.gov&amp;amp;usd=2&amp;amp;usg=ALhdy292R4bTmopfbBINBG0YUaB1Qq3xaA" target="_blank"&gt;grants.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://harvard.edu&amp;amp;usd=2&amp;amp;usg=ALhdy28lz9uKBxGW4ypG_kCj7mYw3uqEZg" target="_blank"&gt;harvard.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://house.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_7_o3B-nDOGrRO8WfXP7LWK5yJFw" target="_blank"&gt;house.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://hp.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_VzCHj28c2uhcn4SsyxVEd7YbmXw" target="_blank"&gt;hp.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ieee.org&amp;amp;usd=2&amp;amp;usg=ALhdy2_qT002G4SesbJtoTUEZuD87TXfmg" target="_blank"&gt;ieee.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://iht.com&amp;amp;usd=2&amp;amp;usg=ALhdy280K5FogwGwN0NQZ6WfO6Wcqd5JWw" target="_blank"&gt;iht.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://indiana.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29EmZfgGEvePta9C0LYyGszkCwhZg" target="_blank"&gt;indiana.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://inria.fr&amp;amp;usd=2&amp;amp;usg=ALhdy29XgPdMlBXfLQ8157u8KEMvaA1nVw" target="_blank"&gt;inria.fr&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://internet2.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-jzylsd0LMhdEdswjMNP5XuaIg9w" target="_blank"&gt;internet2.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://jalbum.net&amp;amp;usd=2&amp;amp;usg=ALhdy29-rOWSz1zmaLzqMlqcKaHFwGSpcg" target="_blank"&gt;jalbum.net&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://keio.ac.jp&amp;amp;usd=2&amp;amp;usg=ALhdy2_OYW_kKrxcpxnFKhVRp3ZmywhBow" target="_blank"&gt;keio.ac.jp&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://loc.gov&amp;amp;usd=2&amp;amp;usg=ALhdy28LcsAo4UU66uMSN4Mnj42MzCgEVA" target="_blank"&gt;loc.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://macromedia.com&amp;amp;usd=2&amp;amp;usg=ALhdy29IJq3QXUtJY9aNnvLlFO1PBfdV9A" target="_blank"&gt;macromedia.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://microsoft.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_COH3RJ-ZMK-wm0JPqyAW_VP_YIw" target="_blank"&gt;microsoft.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://mozilla.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_XQGliUJId49FQJhzIe9Aa0vJWVQ" target="_blank"&gt;mozilla.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://mozilla.org&amp;amp;usd=2&amp;amp;usg=ALhdy2_IfOqLgo_Ut1MuLpytI41QnaS_Bg" target="_blank"&gt;mozilla.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://mysql.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-kq1AngYTJRDhE1yWWaHDLkWv2CQ" target="_blank"&gt;mysql.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nasa.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-TFhlXtkmhq7p0pGYlSWNgZeb32g" target="_blank"&gt;nasa.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nature.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-tB4mWWB_217m1-U7aA3JAKd-Afg" target="_blank"&gt;nature.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://netscape.com&amp;amp;usd=2&amp;amp;usg=ALhdy29rQY9_yRtr903k9TrSRTu8MGDxuw" target="_blank"&gt;netscape.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://newsgator.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_Cj9dCcDSmg-ini55GmFiAn2ys5A" target="_blank"&gt;newsgator.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nih.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-s-lmpFDmSk9gMkh6dxH2MI5BalQ" target="_blank"&gt;nih.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://noaa.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_HCJOE6WvyCFg5TCtA18U2EbyeJQ" target="_blank"&gt;noaa.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://npr.org&amp;amp;usd=2&amp;amp;usg=ALhdy289iACwTstUBk76b7Oiwg9Yc6hZrw" target="_blank"&gt;npr.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nsf.gov&amp;amp;usd=2&amp;amp;usg=ALhdy287TxMPltc3CpiFJgDLAebN_Pd4Cg" target="_blank"&gt;nsf.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nytimes.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_GwrptBkISXPMZk7s618maRvd0Uw" target="_blank"&gt;nytimes.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://opera.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_sr1epIF3TLK35FUi2rWO7BD2KAQ" target="_blank"&gt;opera.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://php.net&amp;amp;usd=2&amp;amp;usg=ALhdy29IPVqOrVDAXSe83q0xfLcmCHpAvg" target="_blank"&gt;php.net&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://plone.org&amp;amp;usd=2&amp;amp;usg=ALhdy28oJJkLg9_1EpL7N19SQmnpjpST5A" target="_blank"&gt;plone.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://real.com&amp;amp;usd=2&amp;amp;usg=ALhdy29zt13-utqviGkDF3OOsPHLMYKe7Q" target="_blank"&gt;real.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://regulations.gov&amp;amp;usd=2&amp;amp;usg=ALhdy281yuRGc_dGKnatkzn2LwrfNjSX9w" target="_blank"&gt;regulations.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://section508.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-7RDL0b1SjRwPQYbPyh2bngeT3cw" target="_blank"&gt;section508.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://senate.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_W3A5Woe24CuhGf_sKtSz4mCscYg" target="_blank"&gt;senate.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://siteground.com&amp;amp;usd=2&amp;amp;usg=ALhdy282NRBeCjcVNdPFx3s1LWf9p19KWg" target="_blank"&gt;siteground.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://slashdot.com&amp;amp;usd=2&amp;amp;usg=ALhdy28qsKXX7_w9P9M2XPHjDi2M-DUNGg" target="_blank"&gt;slashdot.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://slashdot.org&amp;amp;usd=2&amp;amp;usg=ALhdy280-0f34_4y8PN9-oalba6SXL1fpA" target="_blank"&gt;slashdot.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://sourceforge.net&amp;amp;usd=2&amp;amp;usg=ALhdy2-DjJQNpIZz11pSPIyblePjroSJjg" target="_blank"&gt;sourceforge.net&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://sun.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-MY8SBxNdjG8VkwQUsJcfnYkVKpw" target="_blank"&gt;sun.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://times.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-wmNm2Nt8dpX_Z3_9kRloSriv6SQ" target="_blank"&gt;times.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://un.org&amp;amp;usd=2&amp;amp;usg=ALhdy29SL22MJWpQk_XGYqGvelspx0Qq0Q" target="_blank"&gt;un.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://unesco.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-DTP7AMsZjFKOc9UQPaWW5JXyGTA" target="_blank"&gt;unesco.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://upenn.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_tKACYk__OA_5dspcPru5TV0H3aw" target="_blank"&gt;upenn.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://usdoj.gov&amp;amp;usd=2&amp;amp;usg=ALhdy29bHt0BQvUrJlr0I10rUz6447LCzQ" target="_blank"&gt;usdoj.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://va.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2820NgpuSVE1lDOSssQd8oOh20dtQ" target="_blank"&gt;va.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://webstandards.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-i_ugng7U9HlvhmcYs7i8cc1E6EA" target="_blank"&gt;webstandards.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://whitehouse.gov&amp;amp;usd=2&amp;amp;usg=ALhdy29WbxeIQmk8Npg6mtA7-6t7h3kfdw" target="_blank"&gt;whitehouse.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://who.int&amp;amp;usd=2&amp;amp;usg=ALhdy29-9Ltt2sRyH5zjUxBH8np3_1Cc5A" target="_blank"&gt;who.int&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://wired.com&amp;amp;usd=2&amp;amp;usg=ALhdy290DTIUjxpFdNGjZwM1H1tShW0iOA" target="_blank"&gt;wired.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://wordpress.com&amp;amp;usd=2&amp;amp;usg=ALhdy29wxy9YEBKIU1P90qVPnNxmZAghow" target="_blank"&gt;wordpress.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://wordpress.org&amp;amp;usd=2&amp;amp;usg=ALhdy29rKH84T3A8zsxGaxDfxNNSttgZNw" target="_blank"&gt;wordpress.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://yahoo.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-g-rAzd2DFcYZhvI-HTFlXVy8zGg" target="_blank"&gt;yahoo.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://yahoomail.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_DHypn4p4DDkRYHroQNJtSjl65YQ" target="_blank"&gt;yahoomail.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://aaas.org&amp;amp;usd=2&amp;amp;usg=ALhdy28mRiB8kfq943fPCHp70iM0dka55A" target="_blank"&gt;aaas.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://acm.org&amp;amp;usd=2&amp;amp;usg=ALhdy29zUIpmlszhZmMnaB_J82eiHHiIfA" target="_blank"&gt;acm.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://aol.com&amp;amp;usd=2&amp;amp;usg=ALhdy28YTswyNgTXfHSLkywrMea-2WaEkw" target="_blank"&gt;aol.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://aps.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-dywaESLRgUtQRYwucI8NRb2H5pg" target="_blank"&gt;aps.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://archive.org&amp;amp;usd=2&amp;amp;usg=ALhdy29Ov29nHzQIS9bM0uxJ8JTsb9Dw3A" target="_blank"&gt;archive.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://arizona.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_8uZpY8OqjytB8fD9XGL8jEJe5sA" target="_blank"&gt;arizona.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://arxiv.org&amp;amp;usd=2&amp;amp;usg=ALhdy28Tax7eHVRogIRpL-IjtvFCi2tScw" target="_blank"&gt;arxiv.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://asu.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-jLEAi6fEJ3t1QD0A4GzVrWnQnbA" target="_blank"&gt;asu.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://barnesandnoble.com&amp;amp;usd=2&amp;amp;usg=ALhdy282ZoZTiCVcMlC8an8su5mIwzejsQ" target="_blank"&gt;barnesandnoble.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://blogger.com&amp;amp;usd=2&amp;amp;usg=ALhdy29r1IPRmCPRqoP56_uSfWqO1nCxoQ" target="_blank"&gt;blogger.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://brown.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29RPFzM2E9hK5m2GS9LeNqwOepsEg" target="_blank"&gt;brown.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://bu.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_XOSGrMUYFQDSsA7wIMlyKZv7eWQ" target="_blank"&gt;bu.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cbc.ca&amp;amp;usd=2&amp;amp;usg=ALhdy28LnoDZ2ssK5hYRlnHiXhaELSDIAA" target="_blank"&gt;cbc.ca&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cern.ch&amp;amp;usd=2&amp;amp;usg=ALhdy2_tYh5c2TFoU2j5N7chF16d5ZVgfg" target="_blank"&gt;cern.ch&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://cmu.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_HcHGa6yVj8IG6BfRzJBFOXPZOOg" target="_blank"&gt;cmu.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://colorado.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-MRa0AjOgdT31Gb3woI1EQcdvQ7A" target="_blank"&gt;colorado.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://columbia.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-P75KZexqsmG_ms9JQQ0uknJEVwA" target="_blank"&gt;columbia.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://computer.org&amp;amp;usd=2&amp;amp;usg=ALhdy29vXIQeceW8QGmai8kaD15TxoCAKw" target="_blank"&gt;computer.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://debian.org&amp;amp;usd=2&amp;amp;usg=ALhdy29sOeHIcDi870kLWuun1HSVF5eDTw" target="_blank"&gt;debian.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://dmoz.org&amp;amp;usd=2&amp;amp;usg=ALhdy289tQrZV79Odjtne05nhzgaDLZHGw" target="_blank"&gt;dmoz.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://doi.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-XlYTjcpnKzSLmuyrgVcfmJi3QwQ" target="_blank"&gt;doi.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://duke.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29214JY-vhxaqJ_9v7H3zz_NrvfOw" target="_blank"&gt;duke.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://eb.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_5d9InO1S-V68Jl3Xcgtt1RRlcvw" target="_blank"&gt;eb.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ebay.com&amp;amp;usd=2&amp;amp;usg=ALhdy29XkZCjrXYmPw5xE4Hm5_sXyowqUg" target="_blank"&gt;ebay.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://economist.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_T7CqDVSR2F7kxGpFY2MpH3rtvww" target="_blank"&gt;economist.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://energystar.gov&amp;amp;usd=2&amp;amp;usg=ALhdy28_KMck86LcbDuDRXdr5KqtklyJ1w" target="_blank"&gt;energystar.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://excite.com&amp;amp;usd=2&amp;amp;usg=ALhdy29aIE3P8hEOsXXHLcB2zMhiN2d0ag" target="_blank"&gt;excite.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://freshmeat.net&amp;amp;usd=2&amp;amp;usg=ALhdy28qKXLnYC87jw4Z965IjdiwzDD0ow" target="_blank"&gt;freshmeat.net&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://fws.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_bokCIpv78mqWeiltALVvKKrl8vg" target="_blank"&gt;fws.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://gnu.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-ZUImXdgu5zPS93bS1KCD4rBYNmQ" target="_blank"&gt;gnu.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://go.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-rKaUZ_btwLtLBUhIUSZk4LWwa4g" target="_blank"&gt;go.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://google.fr&amp;amp;usd=2&amp;amp;usg=ALhdy2_RFj63jPGG6PNlxMpXbhBzTjbnbg" target="_blank"&gt;google.fr&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://hotbot.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_7aVFNFCL0DSiyCZsRa_P41tf3Lg" target="_blank"&gt;hotbot.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ibm.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_0Jv9e5NeaJ1F8lmxKAai9B_3AvQ" target="_blank"&gt;ibm.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ietf.org&amp;amp;usd=2&amp;amp;usg=ALhdy29c-ILcZBFj_QJomkcsJLfq8b-iMQ" target="_blank"&gt;ietf.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://iie.org&amp;amp;usd=2&amp;amp;usg=ALhdy2_7alIrZmQ8VV3e-62Xxbg94cF6dA" target="_blank"&gt;iie.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://imdb.com&amp;amp;usd=2&amp;amp;usg=ALhdy28ZiZNurlFhhKzjqXo7U_s7cuqRkA" target="_blank"&gt;imdb.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://intel.com&amp;amp;usd=2&amp;amp;usg=ALhdy28jDra5tjZ4nlgA1AAUhrREShdDRg" target="_blank"&gt;intel.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://iom.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-75jJoX9w85UciDvfzxE5qqA4HaQ" target="_blank"&gt;iom.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://itu.int&amp;amp;usd=2&amp;amp;usg=ALhdy28IAPi7QQ_n7yEwt0kDE6Be-ESIRQ" target="_blank"&gt;itu.int&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://java.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_HF_LF3RDZNccOpsUsbAyX25fyiA" target="_blank"&gt;java.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://jhu.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29-e_KLLma2dA2RHIYEjNbBf934HQ" target="_blank"&gt;jhu.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://lycos.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_-9bmPavl3k61YHDplMGf0mpGeIA" target="_blank"&gt;lycos.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://mapquest.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_IJXV6ppK1Ym8B6fvokGzzOsZ9cQ" target="_blank"&gt;mapquest.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://metacrawler.com&amp;amp;usd=2&amp;amp;usg=ALhdy28KIpBrC1ePSNShxzmm1Bxmh-qoGw" target="_blank"&gt;metacrawler.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://msn.com&amp;amp;usd=2&amp;amp;usg=ALhdy29MEmiLtGJjiFtj6cH_2F_kg80tCQ" target="_blank"&gt;msn.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://msnbc.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-ifSrEmFTWT3ahd6FQeO7xXFQMdw" target="_blank"&gt;msnbc.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://msu.edu&amp;amp;usd=2&amp;amp;usg=ALhdy28UjCEx5TUfFucfss9HnbmTJd5Ung" target="_blank"&gt;msu.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nap.edu&amp;amp;usd=2&amp;amp;usg=ALhdy286tqVQXf5CZh5GhV636Uk2y42FoA" target="_blank"&gt;nap.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nas.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-wTl2p4tEbvzO2wFJ-NYJ5r26kxg" target="_blank"&gt;nas.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nationalacademies.org&amp;amp;usd=2&amp;amp;usg=ALhdy29ZmXFyaDJ4ngWAuqXyOxJP3qeWsQ" target="_blank"&gt;nationalacademies.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nist.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-OlERbmvPoSYk1_GBJXZsvvP5hoA" target="_blank"&gt;nist.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nokia.com&amp;amp;usd=2&amp;amp;usg=ALhdy28dhX7gWxrGOMPQJY9yhk7O-cZAaQ" target="_blank"&gt;nokia.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://nrel.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-pXDLeFTOHSRABmM1-mjhazwNUog" target="_blank"&gt;nrel.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://oanda.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-KOxAMEiU6tBgm7yLUM8jVcXfmFw" target="_blank"&gt;oanda.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://opensource.org&amp;amp;usd=2&amp;amp;usg=ALhdy2-5490a2t0vUA6cHa47sA2Qr8jEjg" target="_blank"&gt;opensource.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://oracle.com&amp;amp;usd=2&amp;amp;usg=ALhdy28GhykfsGGVr_slABE87asmLnwMmA" target="_blank"&gt;oracle.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ornl.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2_cflqNoL0biWlUSSF7vyJ5TZHSow" target="_blank"&gt;ornl.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://pbs.org&amp;amp;usd=2&amp;amp;usg=ALhdy29YPQogqDGSAoOEpvqm1aZ1_Q0DOQ" target="_blank"&gt;pbs.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://perl.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-Lh7-9hp09oiuV5lrapdcicRBs-g" target="_blank"&gt;perl.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://pitt.edu&amp;amp;usd=2&amp;amp;usg=ALhdy282g25IVckep55yNUVg0BbmO4SW4A" target="_blank"&gt;pitt.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://princeton.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29EBTwgHU5cp42G4SFVp24Mie3WsQ" target="_blank"&gt;princeton.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://psu.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-UGR_G5cbWAiD6v8qChOhCPJsP4g" target="_blank"&gt;psu.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://python.org&amp;amp;usd=2&amp;amp;usg=ALhdy2_m0gJ-Xn0g4rIKpLPmXecLH4KRvA" target="_blank"&gt;python.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://realnetworks.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-fmq_4qr7Hm92gGyBxHsfJdTijGA" target="_blank"&gt;realnetworks.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://realplayer.com&amp;amp;usd=2&amp;amp;usg=ALhdy298hZaphA95Fnygfq0Cp-YEPN5_fw" target="_blank"&gt;realplayer.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://redhat.com&amp;amp;usd=2&amp;amp;usg=ALhdy28uemxX8TvZ-tCbnnubfNBekuItdw" target="_blank"&gt;redhat.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://rutgers.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_Cr8CUGpmCmxOQmH3UEv6ZpG8Rxw" target="_blank"&gt;rutgers.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://si.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-VJ1qyNm9QOuob5Yn4mTII3IltMQ" target="_blank"&gt;si.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://stanford.edu&amp;amp;usd=2&amp;amp;usg=ALhdy289gUwdqpyEq2CNUuvoHgk8uKU_dA" target="_blank"&gt;stanford.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://statcounter.com&amp;amp;usd=2&amp;amp;usg=ALhdy28ExnU94N0iiFXSxXP0uId3uK2X3g" target="_blank"&gt;statcounter.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://state.gov&amp;amp;usd=2&amp;amp;usg=ALhdy2-fZH-oH3G7NAIcSnsvM1WZBESEGQ" target="_blank"&gt;state.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://truste.org&amp;amp;usd=2&amp;amp;usg=ALhdy29HFosj-_lY3Ig021_19dKRGjFIvg" target="_blank"&gt;truste.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://uci.edu&amp;amp;usd=2&amp;amp;usg=ALhdy28oqrZ_TCSluAnTDA_GasXuZUyAGg" target="_blank"&gt;uci.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://uiuc.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29CD-jpKmrFJBLLT9nLISfGA3ud5Q" target="_blank"&gt;uiuc.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://umd.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-1nISAvVjd6SHWUaPmINOonPiNxQ" target="_blank"&gt;umd.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://umich.edu&amp;amp;usd=2&amp;amp;usg=ALhdy296a4aJ3Kt478BVXeNdAMWyXZmmcA" target="_blank"&gt;umich.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://umn.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29AJuu0g6w5HZbOzkCtzW7bvXJGnQ" target="_blank"&gt;umn.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://unc.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_psVLSgitzx8k6tZfJVN-C34Df0Q" target="_blank"&gt;unc.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://usc.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2_f07ub7yaY8TwYb3CzveK8KsXnVw" target="_blank"&gt;usc.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://usda.gov&amp;amp;usd=2&amp;amp;usg=ALhdy29SEdOeFXTseVKpK6qKZ9j3CCi7ZQ" target="_blank"&gt;usda.gov&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://utexas.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29XE1BA4UGcjaGbBLnFZGWb_oCSBA" target="_blank"&gt;utexas.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://utoronto.ca&amp;amp;usd=2&amp;amp;usg=ALhdy28YgG2VMsG1dzWxVAHGvTgxWaOFrQ" target="_blank"&gt;utoronto.ca&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://verisign.com&amp;amp;usd=2&amp;amp;usg=ALhdy29Wqiq2ovnnmKRadNmwLWjLsSiK5A" target="_blank"&gt;verisign.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://virginia.edu&amp;amp;usd=2&amp;amp;usg=ALhdy28wa4QMKQ5XbaDZd2RuenHEsUutMw" target="_blank"&gt;virginia.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://vlib.org&amp;amp;usd=2&amp;amp;usg=ALhdy29ZUHMgyISBWWaOOmk0dIpHC4CpLQ" target="_blank"&gt;vlib.org&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://washington.edu&amp;amp;usd=2&amp;amp;usg=ALhdy29cKoDFESKlLt53UAO9YFJwHZGgDg" target="_blank"&gt;washington.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://windowsmediaplayer.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-oHWRpqMmNJiJftadmTe2GhxC4Xg" target="_blank"&gt;windowsmediaplayer.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://winzip.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_Hv0rQrCV2jfFbq2qoDM1ImVSo0A" target="_blank"&gt;winzip.com&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://wisc.edu&amp;amp;usd=2&amp;amp;usg=ALhdy2-UZnJaH6jf0obbcC5P1MCE9onB8g" target="_blank"&gt;wisc.edu&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt;Good luck with your backlinks and traffic!&lt;br&gt;&lt;div&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>blogging</category><category>seo</category><guid>https://avilpage.com/2014/01/avil-page-19-get-8-high-pr-dofollow.html</guid><pubDate>Wed, 15 Jan 2014 07:14:00 GMT</pubDate></item><item><title>List of Tollywood Movies Copied from Hollywood Movies</title><link>https://avilpage.com/2014/01/list-of-tollywood-movies-copied-from-hollywood.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: left;"&gt;The first Telugu copycat I came across was Homam. I watched that movie and felt it was great until I watched The Departed. I also had good expectations about Action 3D movie. But after watching the first 15 minutes or so, I severely disappointed as I already watched the Hangover.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Later I came to know a lot about such movies. Here I presented a few movies which I came across.&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;h3 style="text-align: left;"&gt;List Of Telugu Movies Copied/Inspired From English Movies:&lt;/h3&gt;&lt;div style="text-align: left;"&gt;&lt;br&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;table cellpadding="0" cellspacing="0" dir="ltr" style="font-family: arial, sans, sans-serif; font-size: 13px; table-layout: fixed; text-align: center;"&gt;&lt;colgroup&gt;&lt;col width="194"&gt;&lt;col width="259"&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="background-color: white; border: 1px solid rgb(204, 204, 204); direction: ltr; font-size: 100%; font-weight: bold; overflow: hidden; padding: 0px 3px; vertical-align: bottom;"&gt;TOLLYWOOD MOVIE&lt;/td&gt;&lt;td style="background-color: white; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 100%; font-weight: bold; overflow: hidden; padding: 0px 3px; vertical-align: bottom;"&gt;HOLLYWOOD MOVIE&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Maa nana chiranjeevi &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Pursuit of Happiness.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Aatma balam&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Reincarnation of Peter Proud&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Action 3d &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Hangover&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Ahana Pellanta (Allari Naresh) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Marrying the Mafia&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Amaravathi &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Silence of the lambs&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Andaru Dongale Dorikithe&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Excess Baggage.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Anjali &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Son-Rise: A Miracle of Love&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;ANJI &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Indiana Jones and the Last Crusade&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Anthapuram&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Not Without my Daughter.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Apoorva Sahodarulu&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Corsican Brothers&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Arunachalam &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Brewster's Millions&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Bachelors(2000)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;100 girls&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Bhairava dweepam&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Conan the Barbarian (1982)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Bhamane Satyabhamane&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Mrs. Doubtfire&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Bharateeyudu &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Falling Down&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Chandralekha&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;While you were Sleeping.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Chiru Navvutho &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Life is Beautiful (1997)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Chirutha&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Swept Away&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Criminal&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Fugitive.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Dookudu (2011) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Good bye Lenin&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Endukante... Premanta&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Just Like Heaven&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;February 14 Necklace Road  &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;I Know What you did Last Summer (1997)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Gaayam 2 &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;A History Of Violence.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Game (2006)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Changing lanes &lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Ghajini (2008) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Momento (2002)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Hasini   &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Late Autumn (2010)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Hello Brother&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Twin Dragons( Jackie Chan).&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Hero (2008)             &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Police Academy&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Homam (2008)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Departed (2006)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Indrudu Chandrudu&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Moon Over Parador&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Indumathi &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Psycho&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Keka &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Classic &lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Key (2011)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Exam (2009)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Khaidi (1983) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Rambo  First Blood&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Kirathakudu&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Escape from New York( entire 2nd half).&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Manavudu-Danavudu&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Face Off.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Manmadhudu (2002) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;What a woman wants&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Maryada Ramanna &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Our Hospitality &lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Mee Shreyobhalashi(2007)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Japanese Film Ikinai&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Money&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Ruthless People.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Mosagallaku Mosagadu &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Good the Bad and the Ugly&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Mrugaraju  &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Ghost and the Darkness&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Nani &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Big (1988)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Nee manasu naaku telusu&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;On the Line (2001)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Nenu meeku Telusa &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Clean Slate (1994)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Neti Siddartha&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Godfather.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Nirnayam            &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Stakeout&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Oka Vichitram&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Bowfinger&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Oosaravelli &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Vengeance&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Paape Na Praanam&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Nick of Time.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Pilla Zamindar (2011) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;A Millionaire's First Love&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Pothuraju&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Life of David Gale (2003)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Raatri&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Exorcist.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Robo &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Making Mr.Right&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Sakhi&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Barefoot in the Park&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Sathi Leelavathi&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;She Devil&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Satyabhama (2007)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;50 First Dates&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Satyame shivam&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Planes, Trains and Automobiles&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Sisindri (1995)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Baby's Day out&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Siva Shankar&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Road to Perdition.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Stalin (2006) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Pay It Forward (2000)&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Thenali &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;What about Bob?&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Totti Gang&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Saving Silverman.&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Veta (1986) &lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;The Count of Monte Cristo&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;"&gt;Visakha Express (2008)&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;Strangers on a Train&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;</description><category>telugu</category><guid>https://avilpage.com/2014/01/list-of-tollywood-movies-copied-from-hollywood.html</guid><pubDate>Tue, 14 Jan 2014 11:08:00 GMT</pubDate></item><item><title>Start Up Companies In Bangalore</title><link>https://avilpage.com/2014/01/list-of-bangalore-start-up-companies.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;After completion of my B.Tech in 2013, I started looking for start-up companies in Bangalore and here are a few of them I came to know.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://peppersquare.com"&gt;Peppersquare&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Founded in 2002, we are a happily independent digital agency from Bangalore. We work as an extended team to deliver digital services to enterprises, agencies and emerging companies. Our proprietary Digital Maturity Index measures and monitors where brands stand in the digital business future, and offers effective engagement to tap new markets.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://toptomato.in"&gt;Toptomato&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Toptomato is a one-stop online solution for all household needs, spanning the FMCG portfolio of foods, personal care and household care products, thus ushering in a new era of convenient grocery shopping. Leveraging on new-technologies and business strategies, Toptomato is committed to bring in superior service and customer delight.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://foofys.com"&gt;Foofys&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We are a mobile app creation company that also provides digital design services.We see ourselves as crusaders of providing relevant information and this has been our constant striving, creating sustainable solutions that give you the information you need.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://hifives.in"&gt;Hifives&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;HiFives is the flagship product of DealsNow Consumer Solutions Private Limited, an employee applications company. DealsNow develops corporate solutions for employee rewards, recognition, gamification, engagement, collaboration, productivity, work-life balance and other employee focused applications, that can be deployed on the cloud, corporate intranets and mobile platforms. It was founded by IIT-IIM alumni in 2010.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://frrole.com"&gt;Frrole&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Frrole's Social Intelligence Platform currently analyzes almost half a billion data units every month, using the derived insights to create solutions for brands, media and entertainment verticals. We take pride in our ability to answer fuzzy questions, when almost all traditional data analytics stops at providing statistical and keyword based answers.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://fungroo.com"&gt;Fungroo&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A company started by IIM Bangalore Graduates having a customer engagement platform that captures customer feedback in real time from anywhere in this world and helps organizations gain customer insights to take actions at the right time.&lt;/p&gt;
&lt;p&gt;Address:
Fungaroo, C/O Alitum management solutions pvt. ltd, #32, Kormangala inner ring road Bangalore, Karnataka : 560047&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://getmeenabled.com"&gt;Getmeenabled&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;GME Disablity Enablers is an online store for disability equipments and devices (Registration No:Firm/GNR/48/2013-14). GME Disability Enablers mission is to make available world class disability equipments to persons with disability at the door step. This online venture was setup to bridge the gap in availability of suitable devices that empower the disabled to lead independent lives.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://promptcloud.com"&gt;Promptcloud&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;PromptCloud is a Bangalore-based firm dealing with Big Data solutions; where an integral part is web crawling and data extraction. We use cloud computing solutions to facilitate our Data as a Service platform. We work with clients from a range of domains including travel, finance, health-care, marketing, analytics and more.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://metaome.com"&gt;Metaome&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Metaome is a "Big Data" company for the life sciences. We have an agile, customer focused product development strategy and are committed to help scientists glean the best insights and value from data.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://qubole.com"&gt;Qubole&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;At Qubole we’re developing the next generation cloud data platform. With an unparalleled understanding of the cloud and a can do attitude we’re addressing today’s challenges of storing and managing data to create the future: a fast, easy and reliable path to turning Big Data into business insight.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://dreamstarts.in"&gt;Dreamstarts&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;DreamStarts.in is a job search engine for Indian Startups where Startups post job vacancies and potential employees (Talents) apply to the jobs for free. DreamStarts.in targets elite professionals, Marketing Gurus, freelance designers / developers and talented students in India.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://relecura.com"&gt;Relecura&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Relecura is developed by INDUS TechInnovations, a technology company developing innovative products based on knowledge discovery. We provide software solutions to mine knowledge from relevant data. We have developed application-specific technology platforms to organize and deliver knowledge solutions. These enable customers in different verticals to better explore, comprehend, and glean insights from the large and rapidly growing data sets that are of importance in their domains.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://emswebtech.com"&gt;EMSwebtech&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;EMS Webtech is a leading IT solutions company. We provide full-cycle services in the areas of software development, web-based enterprise solutions, web application, portal development, Ecommerce developement, Graphic Design and internet marketing services.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://mydeals247.com"&gt;Mydeals247&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;MyDeals247 offers three unique business models:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A Real-Time MarketPlace (Buy / Sell Model) - No inventory on the website - everything starts from the consumer interest - system notifies the consumer requests to all the sellers whoever selling the particular product or service along with the consumer's budget - sellers make offers against the consumer request along with the offer expiry times - system picks only the top 5 best offers (by lowest price) - totally real-time and rank order changes based on the offers received by the sellers - consumers takes advantage of the best offer and purchase the same.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Volume Based Discounts - deals with only 5 star rated retailers - focus on general house-hold items, entertainment, education, local events, amusement parks, professional training, and services companies - consumer can share the vouchers with friends and colleagues - volume based purchase only - buy more save big!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Introduces personalized Ad display and ‘Pay Per Lead’ model - Displays the local Ads based on the consumer’s interest within the local city at any given point in time. For instance, if someone is looking for the footware and watches in San Francisco, system consolidates all the local Ads relevant to footwear and watches under "San Francisco Talks about..."&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;&lt;a href="http://yourstory.com"&gt;Yourstory&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;YourStory is India’s no.1 media platform for entrepreneurs, dedicated to passionately championing and promoting the entrepreneurial ecosystem in India.&lt;/p&gt;
&lt;p&gt;YourStory was started in October 2008 by Shradha Sharma, who has held senior positions in leading media organizations like The Times of India and CNBC TV18. Today, YourStory is driven by Shradha’s vision to create a hub for thousands of entrepreneurs across India, by providing them with critical value-additions like visibility, business networking, corporate partnerships, growth opportunities and investor connections.&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://inktalks.com"&gt;INKtalks&lt;/a&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To create a community of like-minded peers on unconventional ‘career’ paths, from any field. The experience of being a change-maker is often isolating, as it can lack the financial security, clarity of direction and social network that come with traditional jobs. Being an INK Fellow provides the peer-support necessary to take brilliant work to the next level.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To leverage their impact, through mentorship, support, networks and specially designed opportunities.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To provide them a platform for discovery and exposure like no other, so that our change-makers gain access to potential customers, funding opportunities, accolades and other forms of support critical to their development and success.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;&lt;a href="http://quicksearch.in"&gt;QuickSearch&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We are a local search service focusing on tier 4-5 cities in India. Currently focussing on Chhattisgarh, we are already handling enquiries for 12 odd cities in Chhattisgarh, MP and Jharkhand. With 100k+ data points, many of which are exclusive to us, we aim to put every neighbourhood shop and business online. Imagine searching for and finding online the number of your neighbourhood store even in relatively smaller cities in Jharkhand, Chhattisgarh etc! "&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://housingman.com"&gt;HousingMan&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;"HousingMan brings property buyers and sellers together in one transparent marketplace where both sides get equal opportunity to realize benefits.&lt;/p&gt;
&lt;p&gt;Capabilities
Tools for buyers and property developers/builders to list, browse, research, bid, place discount offers, and track/manage residential property information —all in one place.&lt;/p&gt;
&lt;p&gt;Transparency
A “more windows, fewer walls” approach to real estate: we believe in making information easy to find, keeping all parties clued in, and creating smooth transactions.&lt;/p&gt;
&lt;p&gt;Choices
Users have control, whether customizing listings, choosing to accept an offer, or deciding when to jump into an auction."&lt;/p&gt;
&lt;h4&gt;&lt;a href="http://mplentis.com"&gt;Mplentis&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;MPLENTIS is a WEB Development and SEO Company headquartered in Bangalore, Offering affordable website Design and Development, Responsive Web Design and Development, E-Commerce websites, Content Management System, Content Writing, SEO, Logo Design, Brochure Design and other printing solutions.&lt;/p&gt;
&lt;h4&gt;&lt;a href="https://www.doodleblue.com/"&gt;doodleblue&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Right from mobile application development, web application development, UI/UX, to digital marketing, doodleblue provides a one-stop solution for all your digital needs.&lt;/p&gt;
&lt;p&gt;Feel free to suggest any other companies &lt;a href="http://goo.gl/forms/ne0kRY6LdQc1XP6O2"&gt;to add to this list&lt;/a&gt;.&lt;/p&gt;</description><category>bangalore</category><category>startups</category><guid>https://avilpage.com/2014/01/list-of-bangalore-start-up-companies.html</guid><pubDate>Mon, 13 Jan 2014 11:22:00 GMT</pubDate></item><item><title>తప్పక చదవాల్సిన తెలుగు సామెతలు (Must Read Telugu Proverbs)</title><link>https://avilpage.com/2014/01/must-read-telugu-proverbs.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div&gt;&lt;div style="background-color: white;"&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పల్లెలో ఉన్నప్పుడు సామెతలు ఎక్కువగా   వినిపించేవి. మంచి సామెతలు  విని చాలా  రోజులైంది .  అందుకే ఈ రోజు  సామెతలు  అన్ని గుర్తు చేసుకుంటున్నాను. &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;మొదట కొన్ని ఇంటరెస్టింగ్ సామెతలు... &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అల్లం అంటే నాకు తెలీదా బెల్లంలా పుల్లగా ఉంటదన్నాడట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ He says he very well knew what ginger is and it tastes sour like jaggery! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అమాయకునికి అక్షింతలు ఇస్తే ఆవళికి వెళ్ళి నోట్లో వేసుకున్నాడట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ When a person was given rice grains to bless (the couple), he stepped aside and ate it; out of his innocence! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;మొహమాటానికి పోయి ముండ కడుపు తెచ్చుకుందట&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Being too submissive, a widow gets pregnant ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;సిగ్గు లేని వాడికి నవ్వే సింగారం &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Laughter is the ornament for the shameless. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;శుభం పలకరా పెళ్ళికొడుకు అంటే పెళ్ళికూతురు ముండ ఎక్కడ చాచింది అన్నాడట &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ used to describe a person with a negative attitude and when doing something is very pessimistic about it. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;దమ్మిడి ముండకి ఏగాణి క్షవరం!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Wasting (shaving off) a lot of money on a petty thing! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఆవలింతకు అన్న ఉన్నాడు కాని, తుమ్ముకు తమ్ముడు లేడంట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ It is to be understood that a yawn may lead to another one yawning, but a sneeze does not! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;తగువెలా వస్తుంది జంగందేవరా అంటే బిచ్చం పెట్టవే బొచ్చుముండ అన్నాడుట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ The lady asks the tribal priest how in the world can a quarrel begin. The tribal priest replies back, "Get my alms, bitch! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అఆలు రావు గాని అగ్రతాంబూలం నాకే అన్నాడంట &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Someone who doesnt know the ABCs of the event wants an important place in certain event. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అయ్యకు కోపం సంవత్సరానికి రెండు సార్లే వస్తుంది, వచ్చింది ఆరేసి నెలలు ఉంటుంది&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Man gets angry only twice a year, each for six months ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;మన దీపమని ముద్దులాడితే మూతి కాలకుండా వుంటుందా?&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ If we kiss our candle, doesn't it burn? ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అన్నీ తెలిసినమ్మ అమావాశ్య నాడు చస్తే, ఏమీ తెలియనమ్మ ఏకాదశి నాడు చచ్చిందిట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Lady who knows all dies early and who knows nothing lives lately! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;నిద్ర పోయే వాడిని నిద్ర లేప్పోచు కానీ; నిద్ర పోయిన్నాటు నటిచే వాడిని నిద్ర లేపలెం&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ You can wake up someone who is sleeping; It is impossible to wake up a person who is pretending to be asleep ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పొమ్మనలేక పొగ పెట్టినట్లు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Instead of directly asking someone to leave, making them leave by starting some smoke ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఊరి కోక కోడి ఇస్తే, ఇంటి కోక ఈక అంట.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Distributing less for more people. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పోన్లే పాపమని పాత బట్ట ఇస్తే; గుడి వెనక  పోయి ఉరి వేసుకుందట &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ If you give some clothes for a woman, she used that to hand herself. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పేనుకు పెత్తనం ఇస్తే తల అంత గోరికి పెట్టింది అంట.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Giving authority for wrong people. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;తాటి చెట్టు కింద కూర్చొని పాలు తగిన అది కళ్ళే అనుకుంటారు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Even if you do right things in wrong place, people will think it as wrong. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఇంకా కొన్ని రొటీన్ సామెతలు.... &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అందని ద్రాక్షలు పుల్లన&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ The grapes you can't eat are sour. ] &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అడగందే అమ్మైనా అన్నం పెట్టదు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Even your mother won't give you food if you don't ask. ] &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఆలూలేదు చూలులేదు కొడుకుపేరు సోమలింగం&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ You don't have a wife and she's not pregnant, but your kid's name in Somalingam. ] &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;కుక్క కాటుకి చెప్పు దెబ్బ&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Tit for tat ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;తిన్నింటి వాసాలు లెక్కపెట్టు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[  used when someone who is trusted and helped by a person , cheats his/her benefactor. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt; ఆలస్యం ఆమృతం విషం&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ "A stich in time saves nine". ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పరిగెత్తి పాలు తాగే కంటే ణిల్చిఅని నీళ్ళు తాగటం మేలు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Make use of the available things first before you run for the unavailable ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;చేతులు కాలినాక ఆకులు పట్టుకున్నట్లు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ (no point in) holding medicinal leaves after burning one's hands ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;తంతే గారెల బుట్టలో పడ్డాడుట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ He got kicked into a basket of donuts (meaning, prosperity)! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;కూసే గాడిద వచ్చి మేసే గాడిదను చెరిచిందట!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ A useless person (braying donkey) has distracted another useless person (grazing donkey), nothing really eventful! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఆహారానికి ముందు వ్యవహారానికి వెనుక!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ First for food, last (later) for work! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఆకు యెగిరి ముల్లు మీద పడ్డా, ముల్లు వచ్చి ఆకు మీద పడ్డా, చిరిగేది ఆకే!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ If a leave falls onto a thorn, or vice versa, it is only the leaf that will be torn! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఆస్తి మూరెడు ఆశ బారెడు!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Has tiny bit of money, but wants to buy a lot! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అబద్దమైనా అతికినట్టు ఉండాలి!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Even if it's a lie, it has to stick together! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అద్దం అబద్ధం చెప్పదు!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ A mirror does not lie! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అగ్నికి వాయువు తోడైనట్లు &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Like Wind supporting fire.(Two enemies tied up to act against) ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పిచుక మీద బ్రహ్మాస్త్రం&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Refers to situations where one uses disproportionately excessive force on a weak opponent. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;మింగటానికి మెతుకు లేదు కాని మీసానికి సంపెంగ నూనె &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ we don't have a single rice grain to eat,but we want the aromatic oil for the moustache ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;పొరుగింటి పుల్ల కూర రుచి&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Grass on the other side is greener. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అందితే జుట్టు అందక పోతే కాలు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[  If possible (go for) hair, if not (go for) feet. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఎంకి పెళ్లి సుబ్బి చావు కొచ్చింది&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[  A person is suffering to the maximum because of somebody else's cause. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;వీధిలో పులి ఇంట్లో పిల్లి&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[  A Tiger at home, but a cat outdoors. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;తూర్పు తిరిగి దండం పెట్టు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Tried everything, all we can do now is turn east and pray. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;మొదటికే మోసం మొగుడా అంటే పెసరపప్పు పెళ్ళామా అన్నట్టు &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[  asking people to eat cake when they have no bread ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఇల్లలకగానే పండగ కాదు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ if you have finished painting your home, it does not mean that the festival is over.  ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఆడది తిరిగి చెడుతుంది, మగవాడు తిరగక చెడతాడు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ A woman gets corrupted with too much socializing, and Man gets corrupted with too little ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;మోసే వాడికి తెల్సు కావడి బరువు&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ person carrying the sedan chair knows the weight of it. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఏరిగెటప్పుడు తినొద్దుర అంట్, అద్దుకు తింట అన్నాడట.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ when A suggests to B not to eat while shitting, instead of listening B replies that he will eat with it. ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;అంగట్లో అన్ని ఉన్నా అల్లుడి నోట్లో శని&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ even though you have all you need, you are unable to make business as your son-in-law doesn't talk good about it ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;ఊళ్ళో పెళ్ళి కి కుక్కల హడావిడి&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;[ Dogs eagerness for village marriage! ]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="font-size: large;"&gt;&lt;span style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;div style="line-height: 19.176136016845703px;"&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>proverbs</category><category>telugu</category><guid>https://avilpage.com/2014/01/must-read-telugu-proverbs.html</guid><pubDate>Fri, 10 Jan 2014 12:32:00 GMT</pubDate></item><item><title>Some Frequently Asked Questions About This Blog</title><link>https://avilpage.com/2014/01/avil-page-frequently-asked-questions.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Q: What is Avilpage?&lt;br&gt;A: Just an e-page to write my personal stuff.&lt;br&gt;&lt;br&gt;Q: Why there are no comments on this blog?&lt;br&gt;A: Comments are a good way of interacting and there are many benefits with that but they take a lot of time and I will loose the focus on the topics, so I disabled comments on my blog.&lt;br&gt;&lt;br&gt;Q: No sharing buttons?&lt;br&gt;A: I just removed them and I don't want them here. If you really liked an article, send a message or a mail to your friends about that. That will be great.&lt;br&gt;&lt;br&gt;Q: No Ads?&lt;br&gt;A: Unlike my previous blogs, I am not placing any ads here. I am getting a bad feeling about the ads and soon I will remove the ads from my previous blogs also.&lt;br&gt;&lt;br&gt;Q: No Search?&lt;br&gt;A: Yeah no. Lets say you want to search about "movies". You can go to List of Avil Pages, press "Ctrl + F" and search for movies. If You need a better search go to Google and search "site:avilpage.com movies"&lt;br&gt;&lt;br&gt;Q: Why there is no subscribe button?&lt;br&gt;A: I don't want it to be there. I don't want a mail delivered to your inbox whenever I wrote some nonsense. When you have some free time, just check out here.&lt;br&gt;&lt;br&gt;Q: I need to talk to you. How to contact you?&lt;br&gt;A: Ok, &lt;a href="http://www.avilpage.com/2014/01/avil-page-9-lets-talk.html"&gt;Lets Talk.&lt;/a&gt;&lt;br&gt;&lt;br&gt;Q: Tech details of blog?&lt;br&gt;A: Domain registered with Godaddy and hosted on blogger platform. Using Simple Template.&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>meta</category><guid>https://avilpage.com/2014/01/avil-page-frequently-asked-questions.html</guid><pubDate>Sun, 05 Jan 2014 11:47:00 GMT</pubDate></item><item><title>Top 10 Most Visited Telugu Websites</title><link>https://avilpage.com/2013/12/top-10-most-visited-telugu-websites.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Since my mother tongue is Telugu, I just wanted to look at top ten most famous  Telugu websites. But to my vast surprise, no one has a compiled a list till now. So I took the chance and compiled it. The rankings are based on &lt;a href="http://www.alexa.com/" rel="" target="_blank"&gt;Alexa&lt;/a&gt; ( accurate and famous web traffic measurements ) ranks.&lt;br&gt;&lt;br&gt;There are a few other English websites which are most visited by people of Andhra Pradesh ( considering it as united as of now - Seemandhra and Telangana ). I  considered only Telugu websites ( or which have a Telugu translation )&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table cellpadding="0" cellspacing="0" dir="ltr" style="font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"&gt;&lt;colgroup&gt;&lt;col width="120"&gt;&lt;col width="193"&gt;&lt;col width="147"&gt;&lt;col width="161"&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border: 1px solid rgb(204, 204, 204); direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;Rank in AP&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;India Rank&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;All India Rank&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: solid; border-top-width: 1px; direction: ltr; font-size: 120%; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;World Rank&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;1&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://sakshi.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_TQpsIS6WKA8w1scS8Dzt2UYFpiQ" target="_blank"&gt;sakshi.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;112&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;1534&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;2&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://eenadu.net&amp;amp;usd=2&amp;amp;usg=ALhdy28HxIzT51yXiTAopwaKqiazb_FheQ" target="_blank"&gt;eenadu.net&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;177&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;1966&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;3&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://idlebrain.com&amp;amp;usd=2&amp;amp;usg=ALhdy294EJO8ptnBC66PiJcI9dtcK6g58Q" target="_blank"&gt;idlebrain.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;410&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;4413&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;4&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://andhrajyothy.com&amp;amp;usd=2&amp;amp;usg=ALhdy2-UfemAcRJ8tzOoV7Ej8BdLxb5OIQ" target="_blank"&gt;andhrajyothy.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;593&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;6809&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;5&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://apherald.com&amp;amp;usd=2&amp;amp;usg=ALhdy28NgSHP9HXStpXugwRNYPXULvaZcg" target="_blank"&gt;apherald.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;581&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;7394&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;6&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://namasthetelangaana.com&amp;amp;usd=2&amp;amp;usg=ALhdy29T0KOtzVyML-QuJJCqMnq-iIqtEA" target="_blank"&gt;namasthetelangaana.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;725&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;9377&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;7&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ap7am.com&amp;amp;usd=2&amp;amp;usg=ALhdy2_nqVf_bOpb_YXarQoqzGlg3dWLRA" target="_blank"&gt;ap7am.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;868&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;8104&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;8&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://teluguone.com&amp;amp;usd=2&amp;amp;usg=ALhdy29tfgiJ9v9c3O15Q7jpLE07boC0QQ" target="_blank"&gt;teluguone.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;930&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;10594&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;9&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://ragalahari.com&amp;amp;usd=2&amp;amp;usg=ALhdy292JhxVqpD0ppg7R7yrXFGiuilsCA" target="_blank"&gt;ragalahari.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;1057&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;11567&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 17px;"&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; font-size: 100%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;10&lt;/td&gt;&lt;td style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: solid; border-right-width: 1px; direction: ltr; font-size: 120%; padding: 0px 3px; text-align: center; vertical-align: bottom;"&gt;&lt;a class="in-cell-link" href="https://www.google.com/url?q=http://andhraheadlines.com&amp;amp;usd=2&amp;amp;usg=ALhdy2--KXOdc28Qe58YQU93wdJJQ_cCLg" target="_blank"&gt;andhraheadlines.com&lt;/a&gt;&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; direction: null; font-size: 100.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;---&lt;/td&gt;&lt;td style="border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; font-size: 120.0%; padding: 0px 3px 0px 3px; text-align: center; vertical-align: bottom;"&gt;15383&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt;&lt;br&gt;&lt;/div&gt;</description><category>telugu</category><guid>https://avilpage.com/2013/12/top-10-most-visited-telugu-websites.html</guid><pubDate>Fri, 27 Dec 2013 03:09:00 GMT</pubDate></item><item><title>Using Webcam In Ubuntu - Cheese Installation</title><link>https://avilpage.com/2013/10/avil-page-2-using-webcam-in-ubuntu.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I started using Ubuntu recently and started exploring various features. For screen recording and few other apps, webcam is needed. &lt;/p&gt;
&lt;p&gt;Here I am showing how to use inbuilt webcam in Ubuntu 12.04.&lt;/p&gt;
&lt;p&gt;Open your terminal ( Shortcut: Ctrl + Alt + T ) and run the following command.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;cheese
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the above command is executed, you can find the Cheese app in your application menu. It will take around 3 minutes (~ 18MB)depending on your net speed. &lt;/p&gt;
&lt;p&gt;We can open the app by searching "cheese".&lt;/p&gt;</description><category>ubuntu</category><category>webcam</category><guid>https://avilpage.com/2013/10/avil-page-2-using-webcam-in-ubuntu.html</guid><pubDate>Thu, 10 Oct 2013 01:48:00 GMT</pubDate></item><item><title>Unblock Me Puzzle Solutions</title><link>https://avilpage.com/2013/03/avil-page-unblock-me-all-solutions.html</link><dc:creator>Anand Reddy Pandikunta</dc:creator><description>&lt;p&gt;I like to solve puzzles a lot. I started playing UnblockMe puzzle. I solved all levels. Since some people are asking for solutions, I have screencasted solutions and uploaded them to YouTube.&lt;/p&gt;
&lt;p&gt;Here is a sample screencast.&lt;/p&gt;
&lt;p&gt;&lt;embed width="600" height="400" src="https://youtube.com/v/5qvaJPrzzk0" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/p&gt;
&lt;p&gt;Thanks to Divakar, Nagmohan, Chaitanya, Nagendra for helping with screencast.&lt;/p&gt;</description><category>gaming</category><guid>https://avilpage.com/2013/03/avil-page-unblock-me-all-solutions.html</guid><pubDate>Thu, 21 Mar 2013 06:42:00 GMT</pubDate></item></channel></rss>