Tuesday, June 21, 2016

Fixing DPI Scaling Issues in Skype for Business on Windows 10

My setup for my day job these days is a Surface Pro 4 and either an LG 34UC87M-B or a Dell P2715Q monitor, depending on where I'm working. This is a fantastic setup, but some applications have trouble dealing with the high pixel density and don't scale appropriately.

One case in point is Skype for Business. For some reason it scales correctly as I move between the Surface screen and the external monitor when I use the Dell, but on the LG monitor Skype is either massive on the external monitor, or tiny on the Surface screen.

After a big of digging around I came across a solution that worked for me, which is to change a setting in Skype's manifest file (who knew there was one?). On my machine the file is here:
C:\Program Files\Microsoft Office\Office16\LYNC.EXE.MANIFEST

And the setting in question is this:
<dpiAware>True/PM</dpiAware>

Which I changed to this:
<dpiAware>False/PM</dpiAware>

Note that you'll probably have to edit the file as administrator in order to be able to save it.

Once I made that change, saved the file, and restarted Skype, it now scales correctly for both the Surface screen and the external LG monitor.

Thursday, June 16, 2016

Installing Python 3 and Django on Dreamhost

I'm working on a side project for a friend that has zero budget and since I'm already paying for Dreamhost (my favorite and only choice for shared hosting) and totally underusing it, I figured I'd use this project as my opportunity to figure out how to install Python 3 and Django since A) Dreamhost lets you do install things even on their shared platform (one of the reasons I love them!), and B) the default Python on Dreamhost is Python 2.7.3.

1. Install Python 3.5.1


This part's really simple and Dreamhost even documents it nicely on their knowledge base, but for the sake of one-stop shopping I'll include the steps I performed here. Note that I'm leaving the default Python 2.7.3 in place since I'm not sure what havoc it would wreak to blow it away, so Python 3.5.1 will be installed in such a way that it'll be run as python3. (For the curious, you can also read more about Python at Dreamhost in general.)

Before going any further, if you haven't enabled SSH access for your Dreamhost user you need to do that first since if you can't log in you can't install anything.
  1. Log into the Dreamhost web panel
  2. Click on "Users" and then "Manage Users"
  3. Find the relevant user and click the edit button
  4. Under "User Type" choose "Shell user," and I'd recommend also choosing /bin/bash as the shell type
  5. Scroll to the bottom of the page and click "Save Changes"
Next, we'll install Python 3.5.1.
  1. Go to https://www.python.org/downloads/release/python-351/ and get the URL for the gzipped source tarball.
  2. SSH into your Dreamhost server
  3. In your user's home directory, wget the tgz file using the URL you grabbed in step 1:
    wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
  4. Extract the Python source:
    tar xvf Python-3.5.1.tgz
  5. cd into the extracted source directory:
    cd Python-3.5.1
  6. Configure Python 3.5.1 with a prefix flag so as not to stomp on anything that's already installed:
    ./configure --prefix=$HOME/opt/python-3.5.1
  7. Run make and make install:
    make && make install
  8. Add the new Python installation to your path:
    export PATH=$HOME/opt/python-3.5.1/bin:$PATH
  9. Update your bash profile:
    . ~/.bash_profile
  10. Verify that everything's working (this should output Python 3.5.1):
    python3 -V
If that all looks good at this point, we're ready to proceed and create a virtualenv in which we'll install Django.

2. Create a virtualenv


Python 3 ships with pyvenv, but since it works a bit differently than virtualenv which is what I'm used to using, I decided to install virtualenv and use that. Feel free to use pyenv here if that floats your boat.
  1. Use pip3 to install virtualenv:
    pip3 install virtualenv
  2. Create and/or cd into the directory in which you want to put your virtualenv. I tend to put mine in ~/.virtualenvs, so I did this:
    mkdir ~/.virtualenvs
    cd ~/.virtualenvs
  3. Create a virtualenv to use for our Django project (since we installed virtualenv with pip3 the default Python environment will be Python 3.5.1):
    virtualenv my_django_project
  4. Activate your virtualenv:
    source my_django_project/bin/activate
  5. Confirm everything looks correct at this point (this should output /path/to/virtualenv/bin/python3):
    which python3
If we're still on track we can proceed to install Django.

3. Install Django (and your other requirements)


At this point since we have Python 3.5.1 installed and have successfully created a virtualenv, we can do the usual installation of requirements using pip3, which typically will come from a requirements.txt file. For the sake of illustration we'll go through installing Django into our virtualenv and making sure it works, but pip3 install -r requirements.txt will be the more typical way of installing all the packages you need.
  1. With your virtualenv activated, install Django:
    pip3 install django
  2. Verify everything is working by starting a Python interpreter:
    python3
  3. Import Django to make sure it's in your virtualenv (this shouldn't throw any errors):
    >>> import django
Now that we have verified that our virtualenv is working and sane, we can proceed to the rest of the configuration to get a Django project running successfully in this environment on Dreamhost.

4. Enable Passenger on Your Web Site


Rather than the gunicorn or some of the other WSGI servers you may be familiar with, on Dreamhost you can use either Passenger or FastCGI as the application server for Django applications.

For this post I'll be using Passenger, a tool with which I was not familiar until I saw information about it on Dreamhost. Passenger is apparently more common in Ruby on Rails setups, but it serves the same purpose and falls in the same place in the stack as any of the other WSGI tools with which you may have experience. You can read more about Dreamhost's use of Passenger here and here.

Some Notes About Passenger


Worthy to note about using Passenger on Dreamhost is that once Passenger is enabled, all requests that come into your domain will be handed off to Passenger by Apache. Passenger will first look see if there are any files matching the request in your domain's /public directory (and note that the files must be in the /public directory or subdirectories under /public specifically), and if it can't find an appropriate file, Passenger then tries to handle the request itself.

To provide a couple of concrete examples, let's assume you have a file called hello.html in your domain's /public directory, and a request comes in for http://yourdomain.com/hello.html. Here's what happens next:
  1. Apache hands the request off to Passenger immediately. This is important to note since Apache is out of the picture entirely other than serving as a proxy to Passenger.
  2. Passenger looks for a file called hello.html in your domain's /public directory. Since it finds one, it returns that page to the requester.
Now let's assume a request comes in for http://yourdomain.com/some/django/url. Here's what happens in that case:
  1. Apache hands the request off to Passenger.
  2. Passenger looks for an appropriate file in /public. This time it doesn't find one.
  3. Passenger then attempts to handle the request itself, and since later we'll be configuring Passenger to serve up our Django application using WSGI, at this point Django would be processing the request.

Enable Passenger


In order to run a Django application on Dreamhost we'll need to enable Passenger on the domain on which we're going to run our Django application.
  1. Log into the Dreamhost web panel
  2. Click "Domains" and then click "Manage Domains"
  3. Locate the domain on which you'll be hosting your Django application and click "Edit"
  4. Scroll down and under "Web Options" you'll see a checkbox labeled "Passenger (Ruby/NodeJS/Python apps only)." Check that box.
  5. Scroll to the bottom of the page and click "Change Settings."
That's it for enabling Passenger. Next we'll throw our Django application at Dreamhost and see what sticks.

5. Create a Django App


For the purposes of this post we'll be creating and configuring a Django application directly on the Dreamhost server. Obviously if you have an application that's already written that you want to run on Dreamhost you'd be uploading your application's files as opposed to doing things from scratch on the server, but this should illustrate some of the nuances of what you need to do with your own Django application to get it running on Dreamhost with Passenger.

  1. ssh into the Dreamhost server
  2. Activate the virtualenv you created above:
    source ~/.virtualenvs/my_django_project/bin/activate
  3. cd into the root directory of the web site on which you'll be running your Django application. Note that this is not the aforementioned /public directory under your web site's directory, but the root of the web site itself.
  4. Start a new Django project using django-admin.py:
    python3 django-admin.py startproject my_django_project
  5. Do a quick gut check by firing up the Django development server:
    cd my_django_project
    python3 manage.py runserver
At this point you should see the Django development server start up without any errors. We're nearly there! The last step is to configure this newly created Django application to work with Passenger. But before we do that, a quick note about static files.

Serving Static Files and the Static Root Setting

It wouldn't be Django if we didn't have to stop and say a word about serving static files. Luckily this isn't anything out of the ordinary, but given how Passenger works you do need to be aware of how to set your STATIC_ROOT to make sure everything comes together smoothly.

  1. Create a static directory under your domain's public directory, i.e. you'll wind up with ~/yourdomain.com/public/static
  2. Go into your Django project's settings file and add a STATIC_ROOT setting:
    STATIC_ROOT = os.path.dirname(BASE_DIR) + '/public/static/'
With that you should be all set to run collectstatic and have everything work properly. Now let's move on to configuring Passenger.

6. Configure Passenger


In order to have Passenger load up our Django application, we need to create a passenger_wsgi.py file in the root of our domain. As with all WSGI files this is what tells the application server, in this case Passenger, how to load up the application so it can handle requests.

In the root of your domain, create a passenger_wsgi.py file with the following contents:


With that file in place, you should be able to hit http://yourdomain.com and see the default "Congratulations" Django page. Congratulations indeed! You now have a Django application running on Python 3.5.1 on Dreamhost.

A common error you might run into is something like "no module named foo" or "no module named foo.settings." If you get something along these lines it means your paths are incorrect, so make sure that your Django project is in a directory directly inside your domain's root, not in the /public directory. If that isn't the issue, double-check all the paths in the passenger_wsgi.py file.

Additional Passenger Considerations


It's worth noting that if you change your passenger_wsgi.py file you need to run pkill python to reload the Django application since Passenger loads your application into memory (which is one of its advertised advantages since it makes things pretty zippy).

I also saw note of having to run touch tmp/restart.txt but in my experience I didn't have to do that, so I'm not sure if that's more of a Rails thing or if I simply didn't yet run into situations in which that was necessary. I'm noting it here in the event pkill python doesn't do the trick.

Final Notes


There you have it. You now have the latest Python and Django running on Dreamhost. At this point you can load your own Django project, set up a database (note that Dreamhost only supports MySQL, and even though I much prefer Postgres, MySQL works just fine), and do all the usual Django stuff.

Enjoy!

Monday, June 13, 2016

Installing PyGame with Python 3.5 on Windows 10

Quick installation notes for PyGame with Python 3.5 on Windows 10 since the available installers didn't work for me, the symptom being the apparently highly frequent "pygame module has no attribute init" error when trying to call pygame.init() after importing pygame.

First if you've run any PyGame installers previously, make sure to clean up anything they installed. The easiest way to do this is to run the installer again and choose the uninstall option, but you may also want to check the Lib/site-packages directory under your Python installation to make sure there aren't any remnants.

Next, go here and download the appropriate .whl file for your environment.

Next, open a command prompt and run:
pip install wheel

Finally, browse to the directory where your downloaded .whl file is located and run:
pip install pygame_file_name_here.whl

Restart your command prompt to be safe, and at that point you should be able to do this in a Python interpreter without getting errors:
import pygame
pygame.init()

Hope that saves someone else some head against desk time.

Saturday, December 5, 2015

New Project: "Learning Django REST Framework" Book

Quick announcement that I'm writing a book! Learning Django REST Framework will be published by Packt Publishing around the middle of next year. Excited!

Sunday, November 1, 2015

Python 2.7, Django, Apache, and Gunicorn on CentOS 6.5

I'm working on a little Django project for KPTZ Radio in Port Townsend and since this project has to talk to a serial relay board from a specific server that has other things running on it, I've been going through the process of installing Python 2.7 on CentOS 6.5, along with configuring Django, Apache, and Gunicorn.

Since I'm a lot more used to dealing with Nginx and Gunicorn on Ubuntu, getting this all up and running correctly took a lot more trial and error than I thought it would, but I finally got it figured out so figured I'd share since I found a lot of either incomplete or misleading information about this as I searched for solutions.

Installing Python 2.7

Your first question is probably why I'm not installing Python 3. In the case of this particular project, pyserial was not (when I first started the project) Python 3 compatible, so rather than fight that battle I decided to use Python 2.7.

The problem with Python 2.7 is on CentOS 6.5, Python 2.6.6 is the default, and since there's other Python-related stuff running on the server already I didn't want to run the risk of screwing anything else up, so I had to install Python 2.7 as an alternate Python installation. Luckily there were a couple of resources from people who had already been through this so it wasn't an issue. Here's the steps I took on a fresh CentOS 6.5 VM I was using to do some trial runs before doing everything on the production server (do all these as the root user).

  1. yum -y update
  2. yum -y groupinstall "development tools" --skip-broken
  3. yum -y install wget gcc gcc-c++ make httpd-devel git vim zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
  4. wget https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz
  5. tar xvf Python-2.7.10.tgz
  6. cd Python-2.7.10
  7. ./configure --prefix=/usr/local --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
  8. make && make altinstall
  9. python2.7 -V (to confirm it's working)
  10. cd ..
  11. wget --no-check-certificate https://pypi.python.org/packages/source/s/setuptools/setuptools-18.2.tar.gz
  12. tar xvf setuptools-18.2.tar.gz
  13. cd setuptools-18.2
  14. python2.7 setup.py install
  15. cd ..
  16. curl https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py | python2.7 -
  17. pip2.7 install virtualenv

Create a User to Own the Project

Depending on how you want to do things this could be considered optional, but I created a user to own the project files (again as root):
  1. useradd -m -s /bin/bash/someuser

Create a Python virtualenv and Install the Django Project

Next we'll create a Python 2.7 virtualenv, grab the Django code, install the Django project's requirements, and do a couple of other configuration things for the Django app.
  1. sudo su - someuser
  2. mkdir ~/.virtualenvs
  3. cd ~/.virtualenvs
  4. virtualenv foo --python=python2.7
  5. cd foo
  6. source bin/activate
  7. cd ~/
  8. git clone foo
  9. cd foo
  10. pip install -r requirements.txt
  11. python manage.py runserver (just to make sure things are working at this point)
  12. python manage.py collectstatic
  13. python manage.py migrate

Configure Upstart to Start the Gunicorn Process When the Server Boots

I suppose on the next version of CentOS this will be done with systemd but thankfully on CentOS 6.5 we can still use Upstart. Note that if you're familiar with Upstart on Ubuntu the syntax is quite different on CentOS -- thanks to my good friend and former coworker Brandon Culpepper for pointing that out before I lost my mind.

First, we'll do a quick test to make sure everything's working at this point:
  1. sudo su - 
  2. cd /home/someuser/foo
  3. /home/someuser/.virtualenvs/foo/bin/gunicorn --workers 4 --timeout 60 --bind 0.0.0.0:8000 foo.wsgi:application
  4. Hit Ctrl-C to kill the process if you don't see any errors.
Next we'll create the upstart file:
  1. vim /etc/init/foo.conf
  2. Put the following in the foo.conf file and save it:
    description "Gunicorn process for foo app"

    start on started sshd
    stop on shutdown

    script
      cd /home/someuser/foo
      /home/someuser/.virtualenvs/foo/bin/gunicorn --workers 4 --timeout 60 --log-level debug --bind 0.0.0.0:8000 foo.wsgi:application
    endscript
  3. start foo (to make sure the upstart process works)
  4. ps -wef | grep python (you should see some python processes running under your virtualenv)

Create Apache Virtual Host for the App

There's a bunch of ways to set up Django apps with Apache. In my early days with Django I would have used mod_wsgi but since I'm way more used to Nginx and Gunicorn these days, I figured I'd set up Apache in similar fashion and have it proxy to Gunicorn.
  1. vim /etc/httpd/conf/httpd.conf
  2. Uncomment the NameVirtualHost *.80 line if it isn't already uncommented
  3. Add a new VirtualHost section at the bottom of the Apache config file:
    <VirtualHost *:80>
      ServerName whatever
      DocumentRoot /home/someuser/foo

      # serve static files from Apache
      RewriteEngine on
      RewriteRule ^/static/.* - [L]

      # proxy everything else to the gunicorn process
      ProxyPreserveHost on

      RewriteRule ^(.*)$ http://127.0.0.1:8000$1 [P]
      ProxyPassReverse / http://127.0.0.1:8000/
    </VirtualHost>
  4. apachectl restart
At that point you should be all set! Hope that helps people who are in this same or a similar boat save some time.

Friday, April 24, 2015

Python 3 + Oracle on Ubuntu Server 14.04

I'll invite my readers to check my previous post on this topic to get a sense of how I feel about Oracle.

Small updates it seems to get cx_Oracle working with Python 3 on Ubuntu 14.04. Assume sudo/root for all the following.

  1. Download the RPM versions of both the basic and SDK clients for 11.2.0.4 from http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html
    1. Note: If you're not familiar with the idiotic hell that is Oracle downloads, you have to do this on a browser where you can click a radio button and THEN download, so wget from the server on wish you actually want to install this stuff is unfortunately a no go.
    2. The 12.x version of this stuff still doesn't work with cx_Oracle. At least not for me.
  2. scp the rpm files to the target server
  3. ssh to the target server
  4. apt-get install libaio1 alien
  5. For both the RPMs:
    alien -d RPM_FILE_NAME
  6. For both the newly created Debian packages:
    dpkg -i DEBIAN_PACKAGE_NAME
  7. touch /etc/ld.so.conf.d/oracle.conf
  8. echo "/usr/lib/oracle/11.2/client64/lib" > /etc/ld.so.conf.d/oracle.conf
  9. echo "export ORACLE_HOME=/usr/lib/oracle/11.2/client64" >> /etc/environment
  10. echo "export LD_LIBRARY_PATH=\$ORACLE_HOME/lib" >> /etc/environment
  11. source /etc/environment
  12. ldconfig
  13. pip3 install cx-oracle
  14. Put the relevant tnsnames.ora in $ORACLE_HOME/network/admin
Note that unlike my previous instructions you can install cx_Oracle using pip3 once you have everything in place. Maybe you could use pip before but I seemed to have better luck with the converted RPM, and at that point I was kind of tearing my hair out so I probably didn't go back to take a run at it using pip once the Oracle bits were sorted.

The big change here is the necessity to install both the basic client and the SDK client packages for Oracle; it worked with Python 2.7 on Ubuntu 12.04 without the SDK package.



Friday, March 20, 2015

Speaking at dev.Objective()

I'm very pleased to announce that I've been selected to speak at dev.Objective(), which is coming up in Minneapolis (more specifically Bloomington), MN on May 12-15. (And yes, if the conference name seems vaguely familiar this is the evolution of the former cf.Objective() conference.)

My session is Naked and Afraid: Mobile Offline Access to Emergency Data, in which I'll be discussing how to build cross-platform mobile apps that sync and cache data so you can have access to it even if the Internet and mobile networks are down.

Since I quit doing CFML/ColdFusion several years ago and moved over to Python I stopped speaking at and attending cf.Objective(), but it's a fantastic conference so I'm excited to be making my way back. It's going to be really great to reconnect with a lot of people I haven't seen in quite a while.

If you're a web developer looking for a great conference with a lot of great sessions presented by world-class speakers this is it! Hope to see you there.