Repository navigation
Expand file tree
/
Copy pathcommon.py
More file actions
111 lines (86 loc) · 3.62 KB
/
Copy pathcommon.py
File metadata and controls
111 lines (86 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python3
# This is free and unencumbered software released into the public
# domain.
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a
# compiled binary, for any purpose, commercial or non-commercial, and
# by any means.
# In jurisdictions that recognize copyright laws, the author or
# authors of this software dedicate any and all copyright interest in
# the software to the public domain. We make this dedication for the
# benefit of the public at large and to the detriment of our heirs
# and successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to
# this software under copyright law.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# For more information, please refer to <http://unlicense.org>
"""Things that other scripts import and use.
The markdown files use / as a path separator. That's why they need the
posixpath module for processing paths, but they use functions in this
file when actually opening files.
"""
import itertools
import os
import re
_LINK_REGEX = r'\[(.*?)\]\((.*?)\)'
def find_links(file):
"""Find all markdown links in a file object.
Yield (lineno, regexmatch) tuples.
"""
# don't yield same link twice
seen = set()
# we need to loop over the file two lines at a time to support
# multi-line (actually two-line) links, so this is kind of a mess
firsts, seconds = itertools.tee(file)
next(seconds) # first line is never second line
# we want 1-based indexing instead of 0-based and one-line links get
# caught from linepair[1], so we need to start at two
for lineno, linepair in enumerate(zip(firsts, seconds), start=2):
lines = linepair[0] + linepair[1]
for match in re.finditer(_LINK_REGEX, lines, flags=re.DOTALL):
if match.group(0) not in seen:
seen.add(match.group(0))
yield match, lineno
def get_markdown_files():
"""Yield the names of all markdown files in this tutorial.
This assumes that the README contains links to everything.
"""
yield 'README.md'
with open('README.md', 'r') as f:
for match, lineno in find_links(f):
target = match.group(2)
# Currently the README doesn't link to itself, but I don't
# want to break things if it will in the future.
if target.endswith('.md') and target != 'README.md':
yield target
def askyesno(question, default=True):
"""Ask a yes/no question and return True or False.
The default answer is yes if default is True and no if default is
False.
"""
if default:
# yes by default
question += ' [Y/n] '
else:
# no by default
question += ' [y/N] '
while True:
result = input(question).upper().strip()
if result == 'Y':
return True
if result == 'N':
return False
if not result:
return default
def slashfix(path):
"""Replace / with os.sep."""
return path.replace('/', os.sep)
def slashfix_open(file, mode):
"""An easy way to use slashfix() and open() together."""
return open(slashfix(file), mode)