3 """Software Carpentry Windows Installer
5 Helps mimic a *nix environment on Windows with as little work as possible.
8 * Installs nano and makes it accessible from msysgit
9 * Creates ~/nano.rc with links to syntax highlighting configs
10 * Provides standard nosetests behavior for msysgit
14 1. Install Python, IPython, and Nose. An easy way to do this is with
15 the Anaconda CE Python distribution
16 http://continuum.io/anacondace.html
18 http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git
19 3. Run swc_windows_installer.py
20 You should be able to simply double click the file in Windows
26 from io import BytesIO as _BytesIO
27 except ImportError: # Python 2
28 from StringIO import StringIO as _BytesIO
33 from urllib.request import urlopen as _urlopen
34 except ImportError: # Python 2
35 from urllib2 import urlopen as _urlopen
39 def download(url, sha1):
40 """Download a file and verify it's hash"""
42 byte_content = r.read()
43 download_sha1 = hashlib.sha1(byte_content).hexdigest()
44 if download_sha1 != sha1:
46 'downloaded {!r} has the wrong SHA1 hash: {} != {}'.format(
47 url, download_sha1, sha1))
52 """Split a path into a list of components
54 >>> splitall('nano-2.2.6/doc/Makefile.am')
55 ['nano-2.2.6', 'doc', 'Makefile.am']
59 head, tail = os.path.split(path)
71 def transform(tarinfo, strip_components=0):
72 """Transform TarInfo objects for extraction"""
73 path_components = splitall(tarinfo.name)
75 tarinfo.name = os.path.join(*path_components[strip_components:])
77 if len(path_components) <= strip_components:
83 def tar_install(url, sha1, install_directory, compression='*',
85 """Download and install a tar bundle"""
86 if not os.path.isdir(install_directory):
87 tar_bytes = download(url=url, sha1=sha1)
88 tar_io = _BytesIO(tar_bytes)
89 filename = os.path.basename(url)
90 mode = 'r:{}'.format(compression)
91 tar_file = tarfile.open(filename, mode, tar_io)
92 os.makedirs(install_directory)
94 transform(tarinfo=tarinfo, strip_components=strip_components)
95 for tarinfo in tar_file]
97 path=install_directory,
98 members=[m for m in members if m is not None])
101 def zip_install(url, sha1, install_directory):
102 """Download and install a zipped bundle"""
103 if not os.path.isdir(install_directory):
104 zip_bytes = download(url=url, sha1=sha1)
105 zip_io = _BytesIO(zip_bytes)
106 zip_file = zipfile.ZipFile(zip_io)
107 os.makedirs(install_directory)
108 zip_file.extractall(install_directory)
111 def install_nano(install_directory):
112 """Download and install the nano text editor"""
114 url='http://www.nano-editor.org/dist/v2.2/NT/nano-2.2.6.zip',
115 sha1='f5348208158157060de0a4df339401f36250fe5b',
116 install_directory=install_directory)
119 def install_nanorc(install_directory):
120 """Download and install nano syntax highlighting"""
122 url='http://www.nano-editor.org/dist/v2.2/nano-2.2.6.tar.gz',
123 sha1='f2a628394f8dda1b9f28c7e7b89ccb9a6dbd302a',
124 install_directory=install_directory,
126 home = os.path.expanduser('~')
127 nanorc = os.path.join(home, 'nano.rc')
128 if not os.path.isfile(nanorc):
129 syntax_dir = os.path.join(install_directory, 'doc', 'syntax')
130 with open(nanorc, 'w') as f:
131 for filename in os.listdir(syntax_dir):
132 if filename.endswith('.nanorc'):
133 path = os.path.join(syntax_dir, filename)
134 rel_path = os.path.relpath(path, home)
135 include_path = os.path.join('~', rel_path)
136 f.write('include {}\n'.format(include_path))
139 def create_nosetests_entry_point(python_scripts_directory):
140 """Creates a terminal-based nosetests entry point for msysgit"""
141 contents = '\n'.join([
142 '#!/usr/bin/env/ python',
145 "if __name__ == '__main__':",
146 ' sys.exit(nose.core.main())',
149 if not os.path.isdir(python_scripts_directory):
150 os.makedirs(python_scripts_directory)
151 with open(os.path.join(python_scripts_directory, 'nosetests'), 'w') as f:
155 def update_bash_profile(extra_paths=()):
156 """Create or append to a .bash_profile for Software Carpentry
158 Adds nano to the path, sets the default editor to nano, and adds
159 additional paths for other executables.
163 '# Add paths for Software-Carpentry-installed scripts and executables',
164 'export PATH=\"$PATH:{}\"'.format(':'.join(
165 make_posix_path(path) for path in extra_paths),),
167 '# Make nano the default editor',
168 'export EDITOR=nano',
171 config_path = os.path.join(os.path.expanduser('~'), '.bash_profile')
172 with open(config_path, 'a') as f:
173 f.write('\n'.join(lines))
176 def make_posix_path(windows_path):
177 """Convert a Windows path to a posix path"""
179 (re.compile(r'\\'), '/'),
180 (re.compile('^[Cc]:'), '/c'),
182 windows_path = regex.sub(sub, windows_path)
187 swc_dir = os.path.join(os.path.expanduser('~'), '.swc')
188 bin_dir = os.path.join(swc_dir, 'bin')
189 nano_dir = os.path.join(swc_dir, 'lib', 'nano')
190 nanorc_dir = os.path.join(swc_dir, 'share', 'nanorc')
191 create_nosetests_entry_point(python_scripts_directory=bin_dir)
192 install_nano(install_directory=nano_dir)
193 install_nanorc(install_directory=nanorc_dir)
194 update_bash_profile(extra_paths=(nano_dir, bin_dir))
197 if __name__ == '__main__':