OILS / devtools / pyann.sh View on Github | oils.pub

259 lines, 135 significant
1#!/usr/bin/env bash
2#
3# Usage:
4# types/run.sh <function name>
5
6set -o nounset
7set -o pipefail
8set -o errexit
9
10source devtools/common.sh
11
12readonly PY_PATH='.:vendor/' # note: could consolidate with other scripts
13
14deps() {
15 set -x
16 #pip install typing pyannotate
17
18 # got error with 0.67.0
19 #pip3 install 'mypy==0.660'
20
21 # Without --upgrade, it won't install the latest version.
22 # In .travis.yaml we apparently install the latest version too (?)
23 pip3 install --user --upgrade 'mypy'
24}
25
26checkable-files() {
27 # syntax_abbrev.py is "included" in _devbuild/gen/syntax_asdl.py; it's not a standalone module
28 metrics/source-code.sh osh-files | grep -v syntax_abbrev.py
29 metrics/source-code.sh oil-lang-files
30}
31
32need-typechecking() {
33 # This command is useful to find files to annotate and add to
34 # $MORE_OIL_MANIFEST.
35 # It shows all the files that are not included in
36 # $MORE_OIL_MANIFEST or $OSH_PARSE_MANIFEST, and thus are not yet
37 # typechecked by typecheck-more-oil here or
38 # `types/oil-slice.sh soil-run`.
39
40 build/dynamic-deps.sh osh-eval
41 echo
42
43 comm -2 -3 \
44 <(checkable-files | sort | grep '.py$') \
45 <({ more-oil-manifest; cat _build/NINJA/osh_eval/typecheck.txt; } | sort) \
46 | xargs wc -l | sort -n
47}
48
49readonly -a COMMON_TYPE_MODULES=(_devbuild/gen/runtime_asdl.py _devbuild/gen/syntax_asdl.py)
50
51add-imports() {
52 # Temporary helper to add missing class imports to the 'if
53 # TYPE_CHECKING:' block of a single module, if the relevant
54 # classes are found in one of COMMON_TYPE_MODULES
55
56 # Also, this saves the typechecking output to the file named by
57 # $typecheck_out, to make it possible to avoid having to run two
58 # redundant (and slow) typechecking commands. You can just cat that
59 # file after running this function.
60 local module=$1
61 export PYTHONPATH=$PY_PATH
62 readonly module_tmp=_tmp/add-imports-module.tmp
63 readonly typecheck_out=_tmp/add-imports-typecheck-output
64 set +o pipefail
65 # unbuffer is just to preserve colorization (it tricks the command
66 # into thinking it's writing to a pty instead of a pipe)
67 unbuffer types/run.sh typecheck-files "$module" | tee "$typecheck_out" | \
68 grep 'Name.*is not defined' | sed -r 's/.*'\''(\w+)'\''.*/\1/' | \
69 sort -u | python devtools/findclassdefs.py "${COMMON_TYPE_MODULES[@]}" | \
70 xargs python devtools/typeimports.py "$module" > "$module_tmp"
71 set -o pipefail
72
73 if ! diff -q "$module_tmp" "$module" > /dev/null
74 then
75 cp $module "_tmp/add-imports.$(basename $module).bak"
76 mv "$module_tmp" "$module"
77 echo "Updated $module"
78 fi
79}
80
81#
82# PyAnnotate
83#
84
85# This has a bug
86#pyannotate() { ~/.local/bin/pyannotate "$@"; }
87
88readonly PYANN_REPO=~/git/oils-for-unix/pyannotate/
89
90VENV=_tmp/pyann-venv
91
92make-venv() {
93 python3 -m venv $VENV
94}
95
96install-deps() {
97 . $VENV/bin/activate
98 python3 -m pip install -r $PYANN_REPO/requirements.txt
99}
100
101pyann-patched() {
102 . $VENV/bin/activate
103 local tool=$PYANN_REPO/pyannotate_tools/annotations
104 #export PYTHONPATH=$PYANN_REPO:vendor
105
106 # --dump can help
107 python3 $tool "$@"
108}
109
110
111#
112# Second try
113#
114
115VENV2=_tmp/pyann-venv2
116
117make-venv2() {
118 python3 -m venv $VENV2
119}
120
121install2() {
122 . $VENV2/bin/activate
123 python3 -m pip install pyannotate
124}
125
126tool-demo2() {
127 . $VENV2/bin/activate
128 python3 -m pyannotate_tools.annotations
129}
130
131lib-demo2() {
132 . $VENV2/bin/activate
133 #echo $PYTHONPATH
134
135 # DOES NOT WORK - this is Python 2 code!!!
136 python3 devtools/pyann_driver.py "$@"
137
138 ls -l type_info.json
139 wc -l type_info.json
140}
141
142#
143# Third try - the problem is python2
144#
145
146deps3() {
147 # Gah my custom python2 build doesn't have pip or venv!
148 python2 -m pip install -r $PYANN_REPO/requirements.txt
149}
150
151# September 2019
152PYANN_URL='https://files.pythonhosted.org/packages/0d/26/2f68c02fae0b88d9cefdbc632edad190d61621b5660c72c920be1e52631e/pyannotate-1.2.0.tar.gz'
153
154# October 2019
155MYPY_EXT_URL='https://files.pythonhosted.org/packages/63/60/0582ce2eaced55f65a4406fc97beba256de4b7a95a0034c6576458c6519f/mypy_extensions-0.4.3.tar.gz'
156
157# December 2024
158SIX_URL='https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz'
159
160download-tarballs() {
161 wget --no-clobber --directory _tmp \
162 $PYANN_URL $MYPY_EXT_URL $SIX_URL
163}
164
165PY_PATH_2='.:vendor:_tmp/pyannotate-1.2.0:_tmp/mypy_extensions-0.4.3:_tmp/six-1.17.0'
166
167collect-types() {
168 # syntax error?
169 # Now it requires python3
170 # I think we need an old release
171 # https://pypi.org/project/mypy-extensions/
172 # https://github.com/python/mypy_extensions
173 # TypedDict
174 # https://github.com/python/mypy_extensions/commit/e0c6670e05a87507d59b7d3a0aa2eec88e9813b0
175
176 #local ext=~/git/oils-for-unix/mypy_extensions
177 #export PYTHONPATH=".:$PYANN_REPO:$ext"
178
179 PYTHONPATH=$PY_PATH_2 devtools/pyann_driver.py "$@"
180
181 ls -l type_info.json
182 wc -l type_info.json
183}
184
185osh-pyann() {
186 export PYTHONPATH=".:$PYANN_REPO"
187 PYANN_OUT='a1.json' bin/oil.py osh "$@"
188}
189
190pyann-demo() {
191 rm -f -v *.json
192 osh-pyann -c 'pushd /; echo hi; popd'
193 ls -l *.json
194}
195
196pyann-interactive() {
197 osh-pyann --rcfile /dev/null "$@"
198}
199
200pyann-spec-demo() {
201 local dir=_tmp/pyann-spec
202 mkdir -p $dir
203 export OSH_LIST=bin/osh-pyann
204 test/spec.sh assign --pyann-out-dir $dir "$@"
205
206 ls -l $dir
207}
208
209peek-type-info() {
210 grep path type_info.json | sort | uniq -c | sort -n
211}
212
213apply-types() {
214 local json=${1:-type_info.json}
215 shift
216 #local -a files=(osh/builtin_comp.py core/completion.py)
217 local -a files=(lazylex/*.py doctools/*.py)
218
219 #local -a files=( $(cat _tmp/osh-parse-src.txt | grep -v syntax_asdl.py ) )
220
221 # Use -w to write files
222 set -x
223 PYTHONPATH=$PY_PATH_2 \
224 python2 -m pyannotate_tools.annotations --type-info $json "${files[@]}" "$@"
225
226 #pyann-patched --type-info $json "${files[@]}" "$@"
227}
228
229apply-many() {
230 for j in _tmp/pyann-spec/*.json; do
231 apply-types $j -w
232 done
233}
234
235sub() {
236 local f=$1
237 types/refactor.py sub < $f > _tmp/sub.txt
238 diff -u _tmp/sub.txt $f
239}
240
241audit-hacks() {
242 # I used a trailing _ in a couple places to indicates hacks
243 # A MyPy upgrade might fix this?
244 #egrep -n --context 1 '[a-z]+_ ' osh/*_parse.py
245
246 # spids on base class issue
247 egrep --color -n --context 1 '_temp' osh/*_parse.py
248
249 echo ---
250
251 # a few casts because Id ; is TokenWord.
252 egrep --color -w 'cast' {osh,core,frontend}/*.py
253
254 echo ---
255
256 egrep --color -w 'type: ignore' {osh,core,frontend}/*.py
257}
258
259"$@"