Skip to content

Send the installation scripts results to server #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a78d633
created unique list of failures using set
prerit2010 May 28, 2016
22d8dbe
created a list of failures containing name and version
prerit2010 May 28, 2016
77a5925
Added a function for sending the data to server
prerit2010 May 31, 2016
d2683e9
Added Unique key constraint while sending data to server to identify …
prerit2010 Jun 1, 2016
3a36b63
Changed HOST to global Variable
prerit2010 Jun 7, 2016
393b317
Added system information to request
prerit2010 Jun 7, 2016
c9d73f7
Handled response error messages
prerit2010 Jun 7, 2016
6c244b5
added error description to the failure list
prerit2010 Jun 9, 2016
528b4c4
changed host name
prerit2010 Jun 14, 2016
f8254ee
Fixed unknwon version for failures, and 'the JSON object must be str'…
prerit2010 Jun 16, 2016
8f2d340
fixed error for unknown version
prerit2010 Jun 17, 2016
f51872d
Users are given the option to enter their email id and workshop id. A…
prerit2010 Jun 18, 2016
9f1680e
Removed keyboard interrupt handling because of issues in windows plat…
prerit2010 Jun 22, 2016
87843dd
Updated HOST
prerit2010 Jun 25, 2016
a533054
Added command line argument -H for changing the server to which data …
prerit2010 Jun 26, 2016
bb259dc
Removed global declaration of HOST variable in '__main__'
prerit2010 Jun 26, 2016
009bd8a
Added command line argument option -n for turning off sending data to…
prerit2010 Jun 26, 2016
050fff3
Changed the filename from 'key.txt' to '.swc_submission_id' to keep i…
prerit2010 Jun 29, 2016
c941261
Added '.swc_submission_id' to gitignore
prerit2010 Jun 29, 2016
f6294e3
Separated 'sending to API' code
prerit2010 Jul 5, 2016
5d6f611
Removed .pyc file and added to gitignore
prerit2010 Jul 5, 2016
8c0186d
Separated CHECKS list and calling functions to test the requirements.…
prerit2010 Jul 5, 2016
d661167
Merged script 1 into swc-main.py. So now the script first checks for …
prerit2010 Jul 5, 2016
ffc4453
Changed the download link to python3 instead of python2
prerit2010 Jul 5, 2016
eeba433
Updated the python download link
prerit2010 Aug 15, 2016
c98d912
Added docstring for swc-main.py
prerit2010 Aug 15, 2016
b7bafc0
Modified the docstring of requirements_check.py
prerit2010 Aug 15, 2016
497d864
Changed phrase for taking input of workshop id from user. If the user…
prerit2010 Aug 15, 2016
02618d1
Change the default workshop id to None, and handled it at server side
prerit2010 Aug 15, 2016
b59c22d
Add docstring for api.py
prerit2010 Aug 15, 2016
b0a2f0a
Updated readme
prerit2010 Aug 15, 2016
8969e6d
Merge pull request #9 from prerit2010/split-script
prerit2010 Aug 15, 2016
84eece9
Added travis.yml
prerit2010 Aug 17, 2016
f0202bb
changed exit code to 0
prerit2010 Aug 17, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.swc_submission_id
*.pyc
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
- "3.5"

script:
- python swc-main.py -n
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
For learners
============

This directory contains scripts for testing your machine to make sure
This directory contains script for testing your machine to make sure
you have the software you'll need for your workshop installed. See
the comments at the head of each script for more details, but you'll
basically want to see something like:

$ python swc-installation-test-1.py
$ python swc-main.py
Checking for python version...
Passed
$ python swc-installation-test-2.py
check virtual-shell... pass
check command line shell (virtual-shell)... pass
...
Successes:

virtual-shell Bourne Again Shell (bash) 4.2.37

If you see something like:

$ python swc-installation-test-2.py
$ python swc-main.py
Checking for python version...
Passed
check virtual-shell... fail
check for command line shell (virtual-shell) failed:
Expand All @@ -36,7 +38,7 @@ follow the suggestions to try and install any missing software. For
additional troubleshooting information, you can use the `--verbose`
option:

$ python swc-installation-test-2.py --verbose
$ python swc-main.py --verbose
check virtual-shell... fail
==================
Expand All @@ -48,17 +50,17 @@ option:
For instructors
===============

`swc-installation-test-1.py` is pretty simple, and just checks that
the students have a recent enough version of Python installed that
they'll be able to parse `swc-installation-test-2.py`. The latter
checks for a list of dependencies and prints error messages if a
`swc-main.py` first checks that the students have a recent enough
version of Python installed that they'll be able to parse
`swc-main.py` completely. If python version is found to be at least 2.6,
then it checks for a list of dependencies and prints error messages if a
package is not installed, or if the installed version is not current
enough. By default, the script checks for pretty much anything that
has ever been used at a Software Carpentry workshop, which is probably
not what you want for your particular workshop.

Before your workshop, you should go through
`swc-installation-test-2.py` and comment any dependencies you don't
`swc-main.py` and comment any dependencies you don't
need out of the `CHECKS` list. You might also want to skim through
the minimum version numbers listed where particular dependencies are
defined (e.g. `('git', 'Git', (1, 7, 0), None)`). For the most part,
Expand Down
100 changes: 100 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""
This file sends the data collected by the script 'swc-main.py'
to server.
"""

import json
import sys
import datetime
import platform as _platform

try:
import httplib as http_client
except ImportError:
import http.client as http_client


def submit(successes_list, failures_list, HOST):
"""
This function sends the details of failures and successes to server.
"""

endpoint = "/installation_data/"

try:
with open('.swc_submission_id', 'r') as f:
first_line = f.readline()
unique_id = first_line.split("[key:]")[1]
date = first_line.split("[key:]")[0]
if date != str(datetime.date.today()):
unique_id = None
except:
unique_id = None

successful_installs = []
failed_installs = failures_list
for checker, version in successes_list:
successful_installs.append(
{
"name": checker.full_name(),
"version": version
}
)

user_system_info = {
"distribution_name": _platform.linux_distribution()[0],
"distribution_version": _platform.linux_distribution()[1],
"system": _platform.system(),
"system_version": _platform.version(),
"machine": _platform.machine(),
"system_platform": _platform.platform(),
"python_version": _platform.python_version()
}

headers = {"Content-Type": "application/json"}
data = {
"successful_installs": successful_installs,
"failed_installs": failed_installs,
"user_system_info": user_system_info,
"unique_user_id": unique_id
}

def senddata():
final_data = json.dumps(data)
conn = http_client.HTTPConnection(HOST)
print("\nPushing the data to server....\n")
try:
conn.request("POST", endpoint, final_data, headers=headers)
response = conn.getresponse()
response_string = response.read()
if response.status == 200:
print("\nSuccessfully Pushed to Server!")
response = json.loads(response_string.decode('utf-8'))
unique_id = response.get("key")
file = open('.swc_submission_id', 'w+')
file.write(str(datetime.date.today()) + "[key:]" + unique_id)
else:
print("\nSomething bad happened at Server!")
except:
print("\nConnection could not be established with server!")
conn.close()

global input
try:
input = raw_input # making it compatible for Python 3.x and 2.x
except NameError:
pass
choice = input("\nTo improve our lessons, we gather anonymous data about failed package installations."
" Can we send anonymous list of your packages? (y/N): ")
if choice == 'y' or choice == 'Y':
workshop_id = input("Please enter your workshop name (similar to '2016-08-13-place', ask your instructor for details) (none by default): ")
if not workshop_id:
workshop_id = None
email = input("What is your email address (none by default): ")
if not email:
email = None
data['user_system_info']['email_id'] = email
data['user_system_info']['workshop_id'] = workshop_id
senddata()
else:
return
149 changes: 29 additions & 120 deletions swc-installation-test-2.py → requirements_check.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,45 +1,14 @@
#!/usr/bin/env python

"""Test script to check for required functionality.

Execute this code at the command line by typing:

python swc-installation-test-2.py

Run the script and follow the instructions it prints at the end.

This script requires at least Python 2.6. You can check the version
of Python that you have installed with 'swc-installation-test-1.py'.

By default, this script will test for all the dependencies your
instructor thinks you need. If you want to test for a different set
of packages, you can list them on the command line. For example:

python swc-installation-test-2.py git virtual-editor

This is useful if the original test told you to install a more recent
version of a particular dependency, and you just want to re-test that
dependency.
"""
Some details about the implementation:

# Some details about the implementation:

# The dependencies are divided into a hierarchy of classes rooted on
# Dependency class. You can refer to the code to see which package
# comes under which type of dependency.

# The CHECKER dictionary stores information about all the dependencies
# and CHECKS stores list of the dependencies which are to be checked in
# the current workshop.

# In the "__name__ == '__main__'" block, we launch all the checks with
# check() function, which prints information about the tests as they run
# and details about the failures after the tests complete. In case of
# failure, the functions print_system_info() and print_suggestions()
# are called after this, where the former prints information about the
# user's system for debugging purposes while the latter prints some
# suggestions to follow.
The dependencies are divided into a hierarchy of classes rooted on
Dependency class. You can refer to the code to see which package
comes under which type of dependency.

The CHECKER dictionary stores information about all the dependencies
"""

from __future__ import print_function # for Python 2.6 compatibility

Expand Down Expand Up @@ -79,47 +48,7 @@ def import_module(name):


__version__ = '0.1'

# Comment out any entries you don't need
CHECKS = [
# Shell
'virtual-shell',
# Editors
'virtual-editor',
# Browsers
'virtual-browser',
# Version control
'git',
'hg', # Command line tool
#'mercurial', # Python package
'EasyMercurial',
# Build tools and packaging
'make',
'virtual-pypi-installer',
'setuptools',
#'xcode',
# Testing
'nosetests', # Command line tool
'nose', # Python package
'py.test', # Command line tool
'pytest', # Python package
# SQL
'sqlite3', # Command line tool
'sqlite3-python', # Python package
# Python
'python',
'ipython', # Command line tool
'IPython', # Python package
'argparse', # Useful for utility scripts
'numpy',
'scipy',
'matplotlib',
'pandas',
#'sympy',
#'Cython',
#'networkx',
#'mayavi.mlab',
]
# HOST = "127.0.0.1:5000"

CHECKER = {}

Expand Down Expand Up @@ -232,6 +161,10 @@ def get_url(self):
return url
return self._default_url

def get_data(self):
data = {"error_description" : self.message}
return data

def __str__(self):
url = self.get_url()
lines = [
Expand All @@ -250,8 +183,9 @@ def __str__(self):
def check(checks=None):
successes = []
failures = []
if not checks:
checks = CHECKS
failure_messages = []
# if not checks:
# checks = CHECKS
for check in checks:
try:
checker = CHECKER[check]
Expand All @@ -261,8 +195,16 @@ def check(checks=None):
try:
version = checker.check()
except DependencyError as e:
failures.append(e)
if 'version' not in locals() or version is None:
version = "unknown"
failure_messages.append(e)
_sys.stdout.write('fail\n')
e_data = e.get_data()
failures.append({
"name": checker.full_name(),
"version" : version,
"error_description": e_data.get('error_description')
})
else:
_sys.stdout.write('pass\n')
successes.append((checker, version))
Expand All @@ -274,14 +216,12 @@ def check(checks=None):
version or 'unknown'))
if failures:
print('\nFailures:')
printed = []
for failure in failures:
if failure not in printed:
print()
print(failure)
printed.append(failure)
return False
return True
failure_messages = set(failure_messages)
for failure in failure_messages:
print()
print(failure)
return (False, successes, failures)
return (True, successes, failures)


class Dependency (object):
Expand Down Expand Up @@ -1009,34 +949,3 @@ def print_suggestions(instructor_fallback=True):
print('')
print('For help, email the *entire* output of this script to')
print('your instructor.')


if __name__ == '__main__':
import optparse as _optparse

parser = _optparse.OptionParser(usage='%prog [options] [check...]')
epilog = __doc__
parser.format_epilog = lambda formatter: '\n' + epilog
parser.add_option(
'-v', '--verbose', action='store_true',
help=('print additional information to help troubleshoot '
'installation issues'))
options,args = parser.parse_args()
try:
passed = check(args)
except InvalidCheck as e:
print("I don't know how to check for {0!r}".format(e.check))
print('I do know how to check for:')
for key,checker in sorted(CHECKER.items()):
if checker.long_name != checker.name:
print(' {0} {1}({2})'.format(
key, ' '*(20-len(key)), checker.long_name))
else:
print(' {0}'.format(key))
_sys.exit(1)
if not passed:
if options.verbose:
print()
print_system_info()
print_suggestions(instructor_fallback=True)
_sys.exit(1)
Loading