Skip to content

Commit

Permalink
Merge pull request #1 from artemy/feature/python3
Browse files Browse the repository at this point in the history
Upgrade to python3; move tests out of makefile
  • Loading branch information
artemy authored Mar 17, 2022
2 parents 5134d12 + 45f805e commit e304b77
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 41 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 2.7
- name: Set up Python 3
uses: actions/setup-python@v2
with:
python-version: 2.7
python-version: 3.9
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
pip3 install -r requirements.txt
- name: Test
run: make test
run: python3 -m unittest ns_schedule_test
- name: Build artifact
if: startsWith(github.ref, 'refs/tags/')
run: make build
Expand Down
10 changes: 1 addition & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
PYTHON=python2
PIP=pip
NS_SCHEDULE_PY=ns_schedule.py
NS_SCHEDULE_TEST_PY=ns_schedule_test.py
ALFRED_FILE_NAME=NS_Schedule
ALFRED_PACKAGE_FILES=./alfred/*

.PHONY: clean test build

all: clean test build
all: clean build

clean:
rm -fr out *.alfredworkflow

test:
$(PYTHON) -m pip install --upgrade pip
$(PIP) install -r requirements.txt
$(PYTHON) $(NS_SCHEDULE_TEST_PY)

build:
zip -j -r $(ALFRED_FILE_NAME).alfredworkflow $(ALFRED_PACKAGE_FILES) $(NS_SCHEDULE_PY)
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Alfred workflow for getting NS Train schedule.

### Prerequisites

Project uses standard Python 2.7 shipped with all modern OSX distributions. No dependencies are required for running the
workflow.
Project requires Python 3.8+ to run, which is not included by default with macOS. You can install Python 3 using
this [guide](https://docs.python-guide.org/starting/install3/osx/).

⚠️ Make sure to get API key from https://apiportal.ns.nl/ and set it as workflow environment variable NS_APIKEY during
the installation.
Expand All @@ -36,13 +36,13 @@ you can get more details.
Make sure to first install test dependencies:

```shell
pip install -r requirements.txt
pip3 install -r requirements.txt
```

To run tests, execute

```shell
python -m ns_schedule_test
python3 -m ns_schedule_test
```

If you want to get coverage figures through `coverage` tool:
Expand All @@ -54,9 +54,8 @@ coverage report -m # display coverage figures

## Built With

* [Python 2.7](https://docs.python.org/2.7/)
* [Python 3.8](https://docs.python.org/3.8/)
* [GNU Make](https://www.gnu.org/software/make/manual/make.html) - Build scripting
* [mock](https://mock.readthedocs.org/) - Testing library
* [coverage.py](https://coverage.readthedocs.io/) - Code coverage measurement

## Contributing
Expand Down
4 changes: 2 additions & 2 deletions alfred/info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<key>runningsubtext</key>
<string></string>
<key>script</key>
<string>python ns_schedule.py "{query}"</string>
<string>python3 ns_schedule.py "{query}"</string>
<key>scriptargtype</key>
<integer>0</integer>
<key>scriptfile</key>
Expand Down Expand Up @@ -125,7 +125,7 @@ Make sure to get API key from https://apiportal.ns.nl/ and set it as workflow en
<string>FILLME</string>
</dict>
<key>version</key>
<string>1.0</string>
<string>2.0</string>
<key>webaddress</key>
<string>https://github.com/artemy/alfred-ns-schedule</string>
</dict>
Expand Down
18 changes: 9 additions & 9 deletions ns_schedule.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import json
import os
import sys
import urllib2
import urllib.error
import urllib.parse
import urllib.request
from datetime import datetime
from urllib import urlencode


class NoArgsError(Exception):
Expand All @@ -23,11 +24,11 @@ def create_headers():


def call_api(origin, destination):
params = urlencode({'fromStation': origin, 'toStation': destination})
params = urllib.parse.urlencode({'fromStation': origin, 'toStation': destination})
url = 'https://gateway.apiportal.ns.nl/reisinformatie-api/api/v3/trips?' + params

req = urllib2.Request(url, headers=create_headers())
response = urllib2.urlopen(req)
req = urllib.request.Request(url, headers=create_headers())
response = urllib.request.urlopen(req)
return json.loads(response.read())


Expand All @@ -46,8 +47,7 @@ def duration(time):


def format_date(date):
date = date[:-5] # trim timezone since python 2 doesn't support full ISO notation
return datetime.strptime(date, '%Y-%m-%dT%H:%M:%S').strftime('%H:%M')
return datetime.strptime(date, '%Y-%m-%dT%H:%M:%S%z').strftime('%H:%M')


def create_title(trip):
Expand Down Expand Up @@ -105,7 +105,7 @@ def retrieve_schedule():
return [{'title': 'Please provide origin and destination stations'}]
except ValueError:
return [{'title': 'Can\'t parse server response'}]
except urllib2.HTTPError:
except urllib.error.HTTPError:
return [{'title': 'Error contacting server'}]


Expand All @@ -114,7 +114,7 @@ def create_json(items):


def main(): # pragma: nocover
print(create_json(retrieve_schedule()))
print((create_json(retrieve_schedule())))


if __name__ == '__main__': # pragma: nocover
Expand Down
21 changes: 11 additions & 10 deletions ns_schedule_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import unittest
import urllib2

import mock
import urllib.error
import urllib.parse
import urllib.request
from unittest import mock

from ns_schedule import create_json, create_headers, retrieve_schedule

Expand All @@ -20,8 +21,8 @@ def test_no_api_key(self):
self.assertEqual(expected, retrieve_schedule())

def test_create_json(self):
expected = '{"items": [{"arg": "http://example.com", "subtitle": "Sub1", "title": "Title1"}, ' \
'{"arg": "http://dummy.host", "subtitle": "Sub2", "title": "Title2"}]}'
expected = '{"items": [{"title": "Title1", "subtitle": "Sub1", "arg": "http://example.com"}, ' \
'{"title": "Title2", "subtitle": "Sub2", "arg": "http://dummy.host"}]}'
self.assertEqual(expected, create_json([{"title": "Title1", "subtitle": "Sub1", "arg": "http://example.com"},
{"title": "Title2", "subtitle": "Sub2", "arg": "http://dummy.host"}]))

Expand All @@ -44,7 +45,7 @@ def test_too_many_args(self):
@mock.patch("sys.argv", ["main", "Foo Bar"])
def test_happyflow(self):
with open('testdata/happyflow.json') as json_file:
with mock.patch('urllib2.urlopen') as urlopen_mock:
with mock.patch('urllib.request.urlopen') as urlopen_mock:
mock_response = urlopen_mock.return_value
mock_response.read.return_value = json_file.read()
expected = [{
Expand All @@ -66,7 +67,7 @@ def test_happyflow(self):
@mock.patch("sys.argv", ["main", "Foo Bar"])
def test_happyflow_cancelled(self):
with open('testdata/cancelled.json') as json_file:
with mock.patch('urllib2.urlopen') as urlopen_mock:
with mock.patch('urllib.request.urlopen') as urlopen_mock:
mock_response = urlopen_mock.return_value
mock_response.read.return_value = json_file.read()
expected = [{
Expand All @@ -88,17 +89,17 @@ def test_happyflow_cancelled(self):
@mock.patch("sys.argv", ["main", "Foo Bar"])
def test_malformed_json(self):
with open('testdata/malformed.json') as json_file:
with mock.patch('urllib2.urlopen') as urlopen_mock:
with mock.patch('urllib.request.urlopen') as urlopen_mock:
mock_response = urlopen_mock.return_value
mock_response.read.return_value = json_file.read()
expected = [{"title": "Can\'t parse server response"}]
self.assertEqual(expected, retrieve_schedule())

@mock.patch('urllib2.urlopen')
@mock.patch('urllib.request.urlopen')
@mock.patch("os.environ", {'NS_APIKEY': 'Foo'})
@mock.patch("sys.argv", ["main", "Foo Bar"])
def test_bad_request(self, urlopen_mock):
urlopen_mock.side_effect = urllib2.HTTPError(*[None] * 5)
urlopen_mock.side_effect = urllib.error.HTTPError(*[None] * 5)
expected = [{"title": "Error contacting server"}]
self.assertEqual(expected, retrieve_schedule())

Expand Down
3 changes: 1 addition & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
coverage==5.3.1
mock==3.0.5
coverage==6.3.2

0 comments on commit e304b77

Please sign in to comment.