Categories
Python

Auto Update for your Frozen Python Applications using Esky

Let’s assume you have a desktop application built with Python. It could be a traditional GUI app built with PyQT/wxPython/Kivy or any other GUI framework. Or it could be a web server that serves a browser based HTML GUI for the user. Either way, you have “frozen” the app using cx_freeze, py2app/py2exe or pyinstaller and now you want to add “auto update” to the app, so when there’s a new version of the application is available, the app can download and install the update, automatically. For this particular task, I found esky to be a good viable option. In this article, I am going to demonstrate how we can use esky to deliver updates to our apps.

Quick Introduction to Esky

If we want to use Esky to deliver updates, we need to freeze the app first. But this time, we will ask Esky to freeze the app for us, using our freezer of choice. For example, if we used py2app before, we will still use py2app but instead of directly using it, we will pass it to Esky and Esky will use the py2app to freeze the app for us. This step is necessary so that Esky can inject the necessary parts to handle updates/patches and install them gracefully.

For the apps to locate and download the updates, we need to serve the updates from a location on the internet/local network. Esky produces a zip archive. We can directly put it on our webserver. The apps we freeze needs to know the URL of the webserver and must have access to it.

On the other hand, inside our app, we need to write some codes which will scan the URL of the above mentioned webserver, find any newer updates and install them. Esky provides nice APIs to do these.

So now that we know the steps to follow, let’s start.

Creating a setup file

If you have frozen an app before, you probably know what a setup file is and how to write one. Here’s a sample that uses py2app to freeze an app:

Now we can generate the frozen app using:

This should generate a zip archive in the dist directory.

Hosting the app

Collect the zip file from the dist directory and put it somewhere accessible on the internet. For local testing, you can probably use Python’s built in HTTP server to distribute it.

Finding, Downloading and Installing Updates

Now we will see the client side code that we need to write to locate and install the updates.

Here’s some codes taken from a PyQT app. The find_esky_update method is part of a QMainWindow class. It is called inside the onQApplicationStarted method. So it checks the update as soon as the application starts.

We first check if the app is frozen. If it’s not, then there’s no way we can install updates. sys.frozen will contain information about the app if it’s frozen. Otherwise it will not be available. So we first ensure that it is indeed a frozen app.

Then we create an Esky app instance by providing it the URL of our webserver (where the updates are available). We only pass the root URL (without the zip file name). The find_update() method on the Esky app will find newer update and return some information if a new update is available. Otherwise it will be falsy.

If an update is available, we ask our user if s/he wants to update. Here we used QMessageBox for that. If they agree, we call the auto_update method with a callback. We will see the callback soon. The auto_update downloads the update and installs it. The callback we pass – it gets called every time something happens during the process. It can be a good way to display download progress using this callback.

Let’s see our example code here:

As you can see from the code, the callback gets a dictionary which has a key status and if it is “downloading”, we also have the amount of data we have received so far and the total size. We can use this to calculate the progress and print it. We can also display a nice progress bar if we wish.

So basically, this is all we need to find and install updates.

Rolling a new update

We have learned to use Esky, we have seen how to add auto update to our app. Now it’s time to build a new update. That is easy, we go back to the setup.py file we defined earlier. We had version="0.1", inside the setup() function. We need to bump it. So let’s make it 0.2 and build it. We will get a new zip file (the file contains the version if you notice carefully). Drop it on the webserver (the URL where we put our app). Run an older copy of the app (which includes the update checking codes described above). It should ask you for an update 🙂

Please note, you need to call the find_esky_update() method for the prompt to trigger. As I mentioned above, I run it in onQApplicationStarted method for PyQt. You need to find the appropriate place to call it from in your application.

Further Reading

You can find a nice tutorial with step by step instructions and code samples here: https://github.com/cloudmatrix/esky/tree/master/tutorial

Categories
Django Python

Django: Limiting User Access to Views

In this post, we would like to see how we can limit user accesses to our Django views.

Login Required & Permission Required Decorators

If you have worked with Django, you probably have used the login_required decorator already. Adding the decorator to a view limits access only to the logged in users. If the user is not logged in, s/he is redirected to the default login page. Or we can pass a custom login url to the decorator for that purpose.

Let’s see an example:

There’s another nice decorator – permission_required which works in a similar fashion:

Awesome but let’s learn how do they work internally.

How do they work?

We saw the magic of the login_required and permission_required decorators. But we’re the men of science and we don’t like to believe in magic. So let’s unravel the mystery of these useful decorators.

Here’s the code for the login_required decorator:

By reading the code, we can see that the login_required decorator uses another decorator – user_passes_test which takes/uses a callable to determine whether the user should have access to this view. The callable must accept an user instance and return a boolean value. user_passes_test returns a decorator which is applied to our view.

If we see the source of permission_required, we would see something quite similar. It also uses the same user_passes_test decorator.

Building Our Own Decorators

Now that we know how to limit access to a view based on whether the logged in user passes a test, it’s quite simple for us to build our own decorators for various purposes. Let’s say we want to allow access only to those users who have verified their emails.

Now we can use the decorator to a view like:

Users who have verified their email addresses will be able to access this view. And if they didn’t, they will be redirected to the login view. Using the reason query string, we can display a nice message explaining what’s happening.

Please note, we have used two decorators on the same view. We can use multiple decorators like this to make sure the user passes all the tests we require them to.

Categories
Bangla Data Science

হিস্টোগ্রাম নাকি বার চার্ট?

ডাটা ভিজুয়ালাইজেশনের সময় আমরা প্রায়শই হিস্টোগ্রাম ও বার চার্ট এর ব্যবহার দেখবো । বার চার্ট এবং হিস্টোগ্রাম দেখতে অনেকটা একই রকম । দুটোতেই আমরা লম্বা লম্বা বার আকিঁ । x-axis এ ইন্ডিপেন্ডেন্ট ভ্যারিয়েবল ও y-axis এ ডিপেন্ডেন্ট ভ্যারিয়েবল এর মান বসিয়ে দিয়ে আমরা সুন্দর করে হিস্টোগ্রাম ও বার চার্ট একেঁ ফেলি ।

দেখতে একই রকম হলেও দুটোর মধ্যে রয়েছে মৌলিক পার্থক্য । হিস্টোগ্রাম টা আমরা রেন্জ বা ডিস্ট্রিবিউশানের ক্ষেত্রে ব্যবহার করি । যেমন নিচের হিস্টোগ্রামটা দেখি:

এখানে আমরা দেখছি বিভিন্ন বয়সের মানুষ, যারা ছুটি কাটাতে যায় তাদের মধ্যে কতজন হোটেলে থাকে । আমরা খেয়াল করলে দেখবো, এখানে ২০ বছরের নিচে যারা, তাদের মধ্যে ৫ জন হোটেলে থাকে, ২১-৩০ এর মধ্যে ১৫ জন, ৩১-৪০ এর মধ্যে আছে ১০ জন এবং ৪১-৫০ বয়সীদের মধ্যে ৫ জন এর কম ।

লক্ষ্য করি, এখানে আমাদের ডাটা নিউমেরিক্যাল এবং আমরা রেন্জ নিয়ে কাজ করছি – বয়সের রেন্জ । বিভিন্ন বয়সের মানুষকে নির্দিষ্ট কিছু রেন্জে আমরা ডিস্ট্রিবিউট করেছি । এখানে ডাটার এই রেন্জে কোন গ্যাপ নেই । এবং হিস্টোগ্রামের পার্টগুলোকে বা বার গুলোকে অন্য কোন অর্ডারে রি-এ্যারেন্জ করার সুযোগ নেই ।

এবার দেখি একটি বার চার্ট:

এই চার্টে আমরা দেখছি বিভিন্ন ব্র্যান্ডের গাড়ি নির্মাতাদের জানুয়ারী মাসে বিক্রিত গাড়ির সংখ্যা । এখানে প্রধান লক্ষনীয় বিষয় হলো এইবার আমাদের ডাটা কিন্তু নিউমেরিক্যাল না, বরং ক্যাটেগরিক্যাল । বিভিন্ন ব্র্যান্ডের মধ্যে তুলনা করতে আমরা এই বার চার্টটি ব্যবহার করতে পারি । বার চার্টের ক্ষেত্রে বার গুলোকে রি-এ্যারেন্জ করলেও কোন সমস্যা হয় না । এবং বার গুলো একটা আরেকটার সাথে কানেক্টেড না, মাঝ খানে তাই গ্যাপ থাকে ।


TL;DR – হিস্টোগ্রাম একটা ভ্যারিয়েবলের ডিস্ট্রিবিউশান রিপ্রেজেন্ট করার জন্য ব্যবহার করা হয়, বার চার্ট বিভিন্ন ভ্যারিয়েবলের মধ্যে তুলনা করার জন্য ব্যবহার করা হয় ।