Thursday, September 29, 2016

How to Install Android Studio on Fedora

I have a Fedora system and I need to get Android Studio installed. Here's what I do (following these instructions):

sudo dnf install devassistant
 da pkg install android-studio
da crt android-studio --name my_test
 This uses devassistant. This is a free software program developed by some Red Hat people to help set up development environments.

Unfortunately, it didn't work for me. I got:

INFO: Resolving RPM dependencies with DNF...
Installing 10 RPM packages with DNF. Is this ok? [y(es)/n(o)/s(how)]: y
Installing dependencies ................ Done.
INFO: Android studio was not found on system.
Downloading android studio takes a time. Do you want to continue?
Select [y/n]
y
INFO: Downloading android studio from https://dl.google.com/dl/android/studio/ide-zips/1.3.0.10/android-studio-ide-141.2117773-linux.zip
INFO: Downloading done
INFO: Downloading android SDK from http://dl.google.com/android/android-sdk_r24.3.3-linux.tgz
INFO: Downloading done
INFO: Copy android template project to project destination
INFO: .
[devassistant]$ cp -r /home/ed/.devassistant/files/crt/android-studio/. "my_test"
ERROR: no such snippet: init_add_commit
[ed@localhost ~]$ 
So that's a bummer.

However, it did unpack the android studio tarball into a directory, and by going there and into the bin directory, and running studio.sh, I get a running android studio.

As for devassistant I think I will leave it aside for now and move on to other things. ;-)

WiFi Problems


Android Studio has it's own update manager, and it is trying to download a new version of the SDK (I believe), but it keeps killing the wifi. The download start, but then the wifi melts down and disconnects. The wifi works fine once I disconnect and reconnect it. (I am using a USB wifi for this machine.)

Starting Over

I decided to start over, without devassistant. I went to the android studio download page and hit the download button.

On the install page it asked me to install some packages, so I did:

sudo yum install zlib.i686 ncurses-libs.i686 bzip2-libs.i686

But when I run studio.sh, I get a bunch of java errors.

I think this is a OpenJDK issue, so I am going to try installing Oracle Java.

Installing Oracle Java

I got the correct file from the Oracle Java download page. Double-click on thed rpm and follow the prompts to install.

But in my case, I found it was already installed. OK, that's cool, but why is android studio using OpenJDK?

I really don't need openJDK. I would prefer to have just one java, and no matter what free software purists might say, I want it to be the Oracle java. So I removed OpenJDK according to some intructions here.

[ed@localhost Downloads]$ rpm -qa | grep java
devassistant-dap-java-0.11.1-3.fc24.noarch
javapackages-tools-4.6.0-14.fc24.noarch
tzdata-java-2016f-1.fc24.noarch
java-1.8.0-openjdk-headless-1.8.0.102-1.b14.fc24.x86_64
python3-javapackages-4.6.0-14.fc24.noarch
java-1.8.0-openjdk-1.8.0.102-1.b14.fc24.x86_64
abrt-java-connector-1.1.0-8.fc24.x86_64
java-1.8.0-openjdk-devel-1.8.0.102-1.b14.fc24.x86_64

[ed@localhost Downloads]$ rpm -qa | grep jdk
jdk1.8.0_101-1.8.0_101-fcs.x86_64
java-1.8.0-openjdk-headless-1.8.0.102-1.b14.fc24.x86_64
java-1.8.0-openjdk-1.8.0.102-1.b14.fc24.x86_64
copy-jdk-configs-1.2-1.fc24.noarch
java-1.8.0-openjdk-devel-1.8.0.102-1.b14.fc24.x86_64

But when I tried to remove it, it wanted to remove a bunch of other packages that depend on it, like openoffice. I need those packages so I canceled out of that.


[ed@localhost bin]$ sudo alternatives --config java

There are 2 programs which provide 'java'.

  Selection    Command
-----------------------------------------------
*  1           java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.102-1.b14.fc24.x86_64/jre/bin/java)
 + 2           /usr/java/jdk1.8.0_101/jre/bin/java

Enter to keep the current selection[+], or type selection number: 2

However, no matter what I do, android studio still seems to end up using openJDK

[ed@localhost bin]$ ./studio.sh
OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=350m; support was removed in 8.0
Looking in classpath from com.intellij.util.lang.UrlClassLoader@28c97a5 for /com/sun/jna/linux-x86-64/libjnidispatch.so
Found library resource at jar:file:/home/ed/Downloads/android-studio/lib/jna.jar!/com/sun/jna/linux-x86-64/libjnidispatch.so
Trying /home/ed/.AndroidStudio2.2/system/tmp/jna7490874677544946085.tmp
Found jnidispatch at /home/ed/.AndroidStudio2.2/system/tmp/jna7490874677544946085.tmp
[   4012]   WARN - s.RepoProgressIndicatorAdapter - File /home/ed/.android/repositories.cfg could not be loaded.
[   5834]   WARN - dea.updater.SdkComponentSource - File /home/ed/.android/repositories.cfg could not be loaded.

However, I deleted the previous android-studio directory, and started over. Now it is downloading stuff.


Sunday, September 25, 2016

Build script for Python project on Jenkins using virtualenv

Here's a project build script to use in Jenkins:

PYENV_HOME=$WORKSPACE/.pyenv/
# Delete previously built virtualenv
if [ -d $PYENV_HOME ]; then
    rm -rf $PYENV_HOME
fi
# Create virtualenv and install necessary packages
virtualenv --no-site-packages $PYENV_HOME
. $PYENV_HOME/bin/activate
pip install --quiet httplib2 --upgrade --force-reinstall
pip install --quiet pytest
pip install --quiet pytest-cov
pip install --quiet pylint
python $WORKSPACE/setup.py install
python $WORKSPACE/setup.py develop
pylint -f parseable $WORKSPACE/ats_processor/ | tee pylint.out
py.test $WORKSPACE --junitxml test_results.xml
py.test --cov=$WORKSPACE/ats_processor --cov-report term-missing --cov-report xml
The point of this script is that it uses virtualenv to create a self-contained python execution environment, including using pip to install all necessary packages. This ensures that you are testing with the latest version of each package.

Stripping empty lines from a CSV file with python

In some processing I have to do, the comma-separated value (csv) files I'm using occasionally have a line of empty fields.

For example, instead of:

a,b,c,d,e

I get:

,,,,
Sometimes I get fewer commas, like:

,,

So how to strip these lines out of the file?

I have a function like this:
    @staticmethod
    def row_has_data(row):
        '''
        Detect whether a row in a csv file has data, or is blank.
        '''
        has_data = False
        for col in range(0, len(row)):
            if row[col] != '':
                has_data = True
        return has_data

Then I copy the csv file like this:

    def copy_to_csv(self, infile, has_header, outfile):
        '''
        Copy a file to a csv output file, skipping header if present.
        '''
        csv_writer = csv.writer(outfile, dialect='ats_global_dialect', encoding='UTF-8')
        infile.seek(0)
        csv_data = csv.reader(infile)
        if has_header:
            csv_data.next()  # skip header row
        for row in csv_data:
            if self.row_has_data(row):
                csv_writer.writerow(row)
        outfile.close()

Sunday, September 11, 2016

Python and virtualenv

virtualenv is a tool to create isolated python environments.

I am using virtualenv to package up an installation of a python application for testing in the continuous integration server, Jenkins.

To install virtualenv:

sudo pip install virtualenv

To use virtualenv:

PYENV_HOME=.pyenv/
virtualenv --no-site-packages $PYENV_HOME
. $PYENV_HOME/bin/activate
From then on, everything is in that environment until the deactivate command is issued:

(.pyenv) [ed@localhost ~]$ deactivate

In order to ensure that the application will work on any production machine, the complete set of requirements are loaded by a build script, which launches the python setup.py for the application.

There is a good discussion of virtualenv in the Hitchhikers Guide to Python.

See the vittrualenv docs for more info.

Imports and sys.path

Python finds imported packages by looking at the directories listed in the sys.path.

To check the sys.path:

[ed@localhost ~]$ python -m site
sys.path = [
    '/home/ed',
    '/usr/lib/python27.zip',
    '/usr/lib64/python2.7',
    '/usr/lib64/python2.7/plat-linux2',
    '/usr/lib64/python2.7/lib-tk',
    '/usr/lib64/python2.7/lib-old',
    '/usr/lib64/python2.7/lib-dynload',
    '/usr/lib64/python2.7/site-packages',
    '/usr/lib64/python2.7/site-packages/gtk-2.0',
    '/usr/lib/python2.7/site-packages',
    '/usr/lib/python2.7/site-packages/setuptools-26.1.1-py2.7.egg',
]
USER_BASE: '/home/ed/.local' (exists)
USER_SITE: '/home/ed/.local/lib/python2.7/site-packages' (doesn't exist)
ENABLE_USER_SITE: True

Or, from within python:

[ed@localhost ~]$ python
Python 2.7.12 (default, Sep  2 2016, 14:46:00)
[GCC 6.1.1 20160621 (Red Hat 6.1.1-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, pprint
>>> pprint.pprint(sys.path)
['',
 '/usr/lib/python27.zip',
 '/usr/lib64/python2.7',
 '/usr/lib64/python2.7/plat-linux2',
 '/usr/lib64/python2.7/lib-tk',
 '/usr/lib64/python2.7/lib-old',
 '/usr/lib64/python2.7/lib-dynload',
 '/usr/lib64/python2.7/site-packages',
 '/usr/lib64/python2.7/site-packages/gtk-2.0',
 '/usr/lib/python2.7/site-packages',
 '/usr/lib/python2.7/site-packages/setuptools-26.1.1-py2.7.egg']

How python builds the sys.path is surprisingly complicated. A brief description can be found on Lee on Coding blog post. A more detailed description can be found in this Stackoverflow answer. Also take a look at the python sys.path docs.

The sys.path is put together at load-time by the automatically imported python site module.

The site module evaluates any .pth files it can find