A View from the Prater – IS at DrupalCon Vienna, Day 3

For the past week a group of us from Information Services have been at DrupalCon 2017 in Vienna. We shared our DrupalCon experience on Day 1 and Day 2 of the conference, giving our thoughts on the sessions we attended, recommended top sessions, and our key takeaways.

Thursday was the last day of conference sessions, although for some of us the Drupal work continued with the community code sprint on Friday!

Continue reading “A View from the Prater – IS at DrupalCon Vienna, Day 3”

A View from the Prater – IS at DrupalCon Vienna, Day 2

Enjoying the famous Sachertorte at the Hotel Sacher in Vienna

This week a group of us from Information Services are attending DrupalCon 2017 in Vienna and we are sharing our thoughts on the sessions we attend, recommending top sessions, and giving our key takeaways from our DrupalCon experience. Yesterday I posted our reactions to the first day of DrupalCon, and today we continue our DrupalCon reportage.

For two of our party, Tim Gray and Bruce Darby, this was a very exciting day as they were presenting a session on how we have used code sprints and collaborative development to build a community of users and developers around EdWeb.  More on our first-time DrupalCon Speakers later!

Continue reading “A View from the Prater – IS at DrupalCon Vienna, Day 2”

A View from the Prater – IS at DrupalCon Vienna, Day 1

View of the Prater park in Vienna

As we embark upon our next big adventure, planning for the migration from Drupal 7 to Drupal 8 of EdWeb, the University’s central CMS, a group of us from Information Services are here in Vienna this week attending DrupalCon 2017.  We are a small but diverse bunch of project managers, developers, sysadmins, and support staff who all play a part in building, running and managing EdWeb.  For the next few days we’ll be sharing our thoughts on the sessions we attend, recommending top sessions, and giving our key takeaways – not the wurst variety – from our DrupalCon experience.

On Tuesday, we started DrupalCon the right way by attending the always entertaining Pre-note, followed by Dries Buytaert’s traditional Driesnote keynote presentation on the state of Drupal.  We then set out on our different tracks, paths crossing at coffee and lunch, for the first intense but interesting day of DrupalCon sessions.

Continue reading “A View from the Prater – IS at DrupalCon Vienna, Day 1”

#GasHack – A worthy cause for a weekend of your time!

My brother is a consultant at Raigmore Hospital in Inverness and a colleague is trying to attract interest from industry, computing students or anyone with a bit of computing knowledge in a hack day they are running with the College of Anaesthetists in London (details at: http://gashack.rcoa.it)

The idea is modelled around similar events that have been hosted this year like the NHS Hack day or the MIT hackathon.

Doctors with an idea or project come along and pitch it to the meeting. Developers chose the idea that appeals to them and work on it over the Saturday and Sunday.

On the Sunday afternoon, the teams demo their products in front of the rest of the attendees and a panel of judges.  There are prizes to the teams with the most innovative, exciting or world-changing product.

The event is free and run at the Royal College of Anaesthetists in London; 21st and 22nd of October. It’s a nice venue and they’re buying lunch.

For staff working in IT, it is essentially a charity event.  For students, it’s a nice opportunity to work on real life projects and get something on your CV.

All developer skills are welcome. The theme is around peri-operative care but they will consider any ideas. The clinicians are all intensive care and anaesthetic doctors.

If you would like to help or be involved or just want more information, please get in touch with Michael Leggate (NHS Highland) in the first instance (michaelleggate@nhs.net).  He would be very happy to hear from you.

Thanks.
Bill.

Turing Fest 2017 Reflections

A few members of Information Services (and possibly beyond) attended Turing Fest at the start of August. Turing Fest describes itself as “four conferences in one; covering the product, strategy, engineering and marketing strands of technology. Spread over two days these four tracks shared knowledge and discussed topics at the cutting edge of technology with world-class engineers and technologists from a variety of industries.” It was held at the EICC here in Edinburgh.

Let’s hear how they got on and what thoughts they came away with. Continue reading “Turing Fest 2017 Reflections”

Automation within Information Services Applications Team Delivers Efficiency Gains

Recent work within Information Services Applications has realised benefits by significantly reducing the amount of time required to release APIs (code used by developers to innovate and build further tools).

By utilising tools and technologies which partly automate the work involved in rolling out APIs the Development Services teams have managed to reduce the lead time prior to release from around five days to a matter of minutes.  The tools mean that the release process is significantly more straightforward and requires much less setting up and configuration to the point where releasing an API is almost a case of pushing a button.  The automation also ensures that the process is more reliable and less prone to errors.

Furthermore, multiple APIs can be released in parallel meaning that efficiency gains are further increased as more APIs are developed by the University.

The team demonstrated this new capability in a recent deployment of a microservices tool where several existing APIs were redeployed as part of the release.

Further Information on APIs Programme:

There is a need to transform the online experience of students, applicants, alumni, staff and other members of the University community to provide tailored information via personalised digital services.

To deliver these personalised digital services requires a way to plug into information from central systems and use it in new and innovative ways , like new websites, apps for mobile devices and what’s called ‘portlets’ for MyEd that operate like web pages within web pages.

Plugging into the information can be achieved by using Application Programming Interfaces (APIs). Here at the University we use open source tools for APIs – the type of code you can get from online communities where developers collaborate to make even better products and software.

While API technology has been around for a long time, its use beyond the integration of large, complex business systems has grown rapidly in recent years and with the proliferation of devices and mobile technology, API use in getting data from one place to another – from connecting business systems, to mobile devices and apps – has expanded exponentially.  That’s because APIs allow data to be accessed securely and consistently across multiple devices, a tremendously valuable resource for the University.

The University’s Enterprise APIs Programme (part of Digital Transformation) has been set up to deliver APIs to support projects like the User Centred Portal Pilot, the Service Excellence Programme and other digitalisation and transformation Programmes across the University.  In addition to enhancing central services such as MyEd, APIs will provide a consistent way for software developers across the University to build flexible systems at a lower cost, securely, and consistently across multiple systems.

Further Links:

Digital Transformation Website

API Technology Roadmap

 

6 months of Front-End Development Community

As we are reaching the end of the University’s financial year, I thought this would be a good time to look back on the first year of the Front-End Development Community. The community began in the fall of 2016, when I was awarded a bit of money for this idea from the Innovation Fund. My idea was to create a community where people interested in front-end development could come together from across the University, to discuss ideas and share best practice.

A few months were spent on the initial brainstorming and organisation, so the community didn’t really get started until February 2017. Over the course of 6 months, we have put on 7 highly successful events:

  • 2 industry talks (from Harry Roberts and Chad Gowler)
  • 3 community lightning talk sessions
  • 2 talks on Designing for IT Accessibility (from Viki Galt)

I’ve been greatly helped by the hard work and dedication of my colleagues, without whom we wouldn’t have been able to accomplish this.

Overall, we have had an impressive total of 280 registrations for events, with 188 different attendees. This shows that we have a dedicated core group who are actively engaged in participating in the community.  Continue reading “6 months of Front-End Development Community”

Chad Gowler: Asking About Gender

The University’s Front-End Development Community and Playfair Steps recently hosted Chad Gowler (http://www.kitation.co.uk/) to give a talk on “Asking About Gender”. This thought-provoking talk promotes awareness of some of the challenges faced by non-binary and gender-variant users, and discusses how we can support their needs in web development.

Slides and an alternate recording can be found here (note that this recording is for an older version and doesn’t cover all of the material in the slides):

This is the second time that I have been fortunate enough to see Chad give this talk. One of the things I really enjoy is that it demonstrates how we need to continually ask ourselves why we are asking these types of questions in the first place. This gets straight to the heart of user-centred design.

For our last talk from Harry Roberts, I wrote up some information about who was in the audience, so I thought it would be interesting to do a comparison. Again, the numbers are taken from our Event Booking system, so only shows who signed up for the event. This won’t be exact, as some people may have booked but not attended (or the other way around). Continue reading “Chad Gowler: Asking About Gender”

Writing Python command-line tools with cliff

As part of the Keepsafe Europe project at EDINA, we needed to build a tool to help us understand and manipulate files sent to us by publishers. We didn’t know much about the data formats we’d get (other than, as always, they would be completely inconsistent), but we knew that we would have to manipulate them in various ways, and bring them into a roughly standard format to interact with an API we’d built. We also knew we would have to be able to script this so that we could run it in the future with different data, and enable others outside the university to do this sort of manipulation for themselves.

As a first-step, we wanted to build a command-line application which would let us manipulate CSV-like data and submit requests to our API. Luckily, using Python for this turned out to be pretty simple, thanks to a framework called cliff. I couldn’t find much about cliff online, so I thought I’d write up a quick intro/advert for it here.

Python’s built-in argparse module already makes it straight-forward to build command-line scripts that take in arguments and handle them sensibly. What cliff does is build on top of that, allowing you to make an entire application with: subcommands (think git add, git commit, git ...); an interactive shell; base classes for common types of commands such as listing data; and output  formatted in a variety of fashions.

I’m going to work through a very basic, stripped-down version of our app, to help you get a feel for what cliff can do.

First, setup an environment and install cliff in the standard fashion:

$ virtualenv -p /usr/bin/python3 env
$ source env/bin/activate
$ pip install cliff

Then, create a module, which I’ll just call app.py:

import os
import sys

from cliff.app import App
from cliff.command import Command
from cliff.commandmanager import CommandManager
from cliff.show import ShowOne

data = [
    [ 'Journal', 'Publisher', 'Print ISSN', 'Online ISSN' ],
    [ 'Journal of Software', 'Computer Publishings', '0000-0000', '0000-0001' ],
    [ 'Journal of Hardware', 'Computer Publishings', '1111-0000', '1111-0001' ],
    [ 'Software Development Monthly', 'Megacorp', '2222-0000', '2222-0001' ],
    [ 'Hardware Letters', 'XIT University Press', '3333-0000', '3333-0001' ],
]

class MyApp(App):

    def __init__(self):
        super().__init__(
            description='Does some awesome stuff',
            version='0.1',
            command_manager=CommandManager('myapp'),
            deferred_help=True,
        )

    def initialize_app(self, argv):
        commands = [ Select, ]
        for command in commands:
            self.command_manager.add_command(command.__name__.lower(), command)

class Select(ShowOne):
    'display details of journal with given title'

    def get_parser(self, prog_name):
        parser = super().get_parser(prog_name)
        parser.add_argument('title', help='Title of journal to show')
        return parser

    def take_action(self, parsed_args):
        headers = data[0]
        for d in data[1:]:
            if d[0] == parsed_args.title:
                return (headers, d)
        return (None, None)

def main(argv=sys.argv[1:]):
    myapp = MyApp()
    return myapp.run(argv)

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))

You’ll also need to add a module called setup.py:

#!/usr/bin/env python

from setuptools import setup, find_packages

setup(
    name='myapp',
    version='0.1',
    description='Does awesome stuff',
    author='Steven Carlysle-Davies',
    author_email='steven.carlysle-davies@ed.ac.uk',
    entry_points={
        'console_scripts': [
            'myapp = app:main'
        ],
    },
)

Then, you just need to install your application into your environment:

$ pip install -e .

That’s it, you now have a full (if somewhat minimal) application ready to interact with:

$ myapp select "Journal of Software"
+-------------+----------------------+
| Field       | Value                |
+-------------+----------------------+
| Journal     | Journal of Software  |
| Publisher   | Computer Publishings |
| Print ISSN  | 0000-0000            |
| Online ISSN | 0000-0001            |
+-------------+----------------------+

You can also get the data in a different format:

$ myapp select -f json "Hardware Letters"
{
 "Online ISSN": "3333-0001",
 "Publisher": "XIT University Press",
 "Journal": "Hardware Letters",
 "Print ISSN": "3333-0000"
}

And use the interactive application:

$ myapp
(myapp) help select
usage: select [-h] [-f {json,shell,table,value,yaml}] [-c COLUMN]
 [--prefix PREFIX] [--max-width <integer>] [--print-empty]
 [--noindent]
 title

display details of journal with given title

positional arguments:
 title Title of journal to show

optional arguments:
 -h, --help show this help message and exit

...
(myapp) select -f value "Journal of Hardware"
Journal of Hardware
Computer Publishings
1111-0000
1111-0001
(myapp) quit
$

As you can see, a fairly powerful range of functionality for not much code. Let’s take a closer look at what’s going on.

First, we override the default constructor to App with some parameters to let cliff know what our application is and what it does, which is used in the generated help.

    def __init__(self):
        super().__init__(
            description='Does some awesome stuff',
            version='0.1',
            command_manager=CommandManager('myapp'),
            deferred_help=True,
        )

Next, we need to tell cliff what commands are available.

    def initialize_app(self, argv):
        commands = [ Select, ]
        for command in commands:
            self.command_manager.add_command(command.__name__.lower(), command)

The recommended way of doing this is actually through specifying entry-points in your setup.py. That would complicate this example, and in practice we’ve actually found that it’s more readable to specify them directly in your application, instead of having to edit a list in two places.

Next we define the command class. We’re inheriting from a built-in cliff command called ShowOne, which is useful for any commands where you want to show the details of one ‘thing’, e.g. a row, a file etc. The docstring is again used in the generated help text.

class Select(ShowOne):
    'display details of journal with given title'

Then, we specify what arguments our command takes. This uses the built-in argparse module, but cliff has already added some common options to it in the parent class. All we’re adding is that we take in one required argument, called ‘title’.

    def get_parser(self, prog_name):
        parser = super().get_parser(prog_name)
        parser.add_argument('title', help='Title of journal to show')
        return parser

Finally, we need a subroutine that actually does all the work once the command is called. This gets given the arguments that have been parsed according to the parser defined above, and ShowOne expects the subroutine to return a 2-tuple of (headers, values). In our case, we’re just looping through the data to find the matching row (and not handling errors very gracefully!).

    def take_action(self, parsed_args):
        headers = data[0]
        for d in data[1:]:
            if d[0] == parsed_args.title:
                return (headers, d)
        return (None, None)

In our actual application, this subroutine is often usually just a line or two long, taking in the parsed_args variable and extracting the values to pass to another subroutine elsewhere in our application. That allows us to test the logic of the code more easily.

Last, we need a bit of boilerplate that’ll be in almost all your cliff applications, but this is what actually instantiates your application and passes through the parameters from the command-line.

def main(argv=sys.argv[1:]):
    myapp = MyApp()
    return myapp.run(argv)

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))

I’m going to gloss over setup.py, but it’s part of setuptools, and there’s more information about how cliff interacts with it in the cliff documentation.

As you can see, quite a lot of the above code is just needed to initialise the application , and only a small part is actually needed to define the select command. Let’s add another command, one that displays multiple rows of the data:

from cliff.lister import Lister
...
commands = [ Filter, Select, ]
...
class Filter(Lister):
    'display selected columns of the data'

    def get_parser(self, prog_name):
        parser = super().get_parser(prog_name)
        parser.add_argument('--index', action='store_true', help='Use column index numbers instead of names')
        parser.add_argument('column', nargs='+', help='Selected columns to display')
        return parser

    def take_action(self, parsed_args):
        if parsed_args.index:
            columns = [int(c) for c in parsed_args.column]
        else:
            columns = [data[0].index(c) for c in parsed_args.column]

        selected = [ [d[c] for c in columns] for d in data ]
        return (selected[0], selected[1:])

This command uses the other major built-in cliff command, Lister. This is similar to ShowOne, but used where you want to display a list of things to the user. This time, we’re letting the user give us a list of columns to display. If they specify --index, they can give us column indices instead of headers.

$ myapp filter "Journal" "Publisher"
+------------------------------+----------------------+
| Journal                      | Publisher            |
+------------------------------+----------------------+
| Journal of Software          | Computer Publishings |
| Journal of Hardware          | Computer Publishings |
| Software Development Monthly | Megacorp             |
| Hardware Letters             | XIT University Press |
+------------------------------+----------------------+

$ myapp filter --format json --index 1 2
[
 {
 "Publisher": "Computer Publishings",
 "Print ISSN": "0000-0000"
 },
 {
 "Publisher": "Computer Publishings",
 "Print ISSN": "1111-0000"
 },
 {
 "Publisher": "Megacorp",
 "Print ISSN": "2222-0000"
 },
 {
 "Publisher": "XIT University Press",
 "Print ISSN": "3333-0000"
 }
]

$ myapp help filter
usage: myapp filter [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN]
 [--noindent] [--quote {all,minimal,none,nonnumeric}]
 [--max-width <integer>] [--print-empty] [--index]
 column [column ...]

display selected columns of the data

positional arguments:
 column Selected columns to display

optional arguments:
 -h, --help show this help message and exit
 --index Use column index numbers instead of names
...

There’s a lot more to cliff, but hopefully this has given you a taste for what it can do. We’ve found it trivially easy to implement commands, and let cliff handle all the complications of parsing arguments and formatting the output appropriately. It lets us easily build scripts that manipulate data (and let others who don’t know Python build the same scripts). For anyone looking to build quick and powerful command-line applications, I’d highly recommend it.