@@ -29,19 +29,29 @@ class Helpers {
29
29
30
30
See https://github.com/airbytehq/airbyte/issues/4979 for original context
31
31
"""
32
- if (project. file(testFilesDirectory). exists()) {
33
32
33
+ if (project. file(testFilesDirectory). exists()) {
34
+ def outputArg = project. hasProperty(' reports_folder' ) ? " -otemp_coverage.xml" : " --skip-empty"
35
+ def coverageFormat = project. hasProperty(' reports_folder' ) ? ' xml' : ' report'
36
+ def testConfig = project. file(' pytest.ini' ). exists() ? ' pytest.ini' : project. rootProject. file(' pyproject.toml' ). absolutePath
34
37
project. projectDir. toPath(). resolve(testFilesDirectory). traverse(type : FileType . FILES , nameFilter : ~/ (^test_.*|.*_test)\. py$/ ) { file ->
35
38
project. task(" _${ taskName} Coverage" , type : PythonTask , dependsOn : taskDependencies) {
36
39
module = " coverage"
37
- command = " run --data-file=${ testFilesDirectory} /.coverage.${ taskName} --rcfile=${ project.rootProject.file('tools/python/.coveragerc ').absolutePath} -m pytest -s ${ testFilesDirectory} "
40
+ command = " run --data-file=${ testFilesDirectory} /.coverage.${ taskName} --rcfile=${ project.rootProject.file('pyproject.toml ').absolutePath} -m pytest -s ${ testFilesDirectory} -c ${ testConfig } "
38
41
}
39
42
// generation of coverage report is optional and we should skip it if tests are empty
43
+
40
44
project. task(taskName, type : Exec ){
41
45
commandLine = " .venv/bin/python"
42
- args " -m" , " coverage" , " report " , " --data-file=${ testFilesDirectory} /.coverage.${ taskName} " , " --rcfile=${ project.rootProject.file('tools/python/.coveragerc ').absolutePath} "
46
+ args " -m" , " coverage" , coverageFormat , " --data-file=${ testFilesDirectory} /.coverage.${ taskName} " , " --rcfile=${ project.rootProject.file('pyproject.toml ').absolutePath} " , outputArg
43
47
dependsOn project. tasks. findByName(" _${ taskName} Coverage" )
44
48
setIgnoreExitValue true
49
+ doLast {
50
+ // try to move a generated report to custom report folder if needed
51
+ if (project. file(' temp_coverage.xml' ). exists() && project. hasProperty(' reports_folder' )) {
52
+ project. file(' temp_coverage.xml' ). renameTo(project. file(" ${ project.reports_folder} /coverage.xml" ))
53
+ }
54
+ }
45
55
46
56
}
47
57
// If a file is found, terminate the traversal, thus causing this task to be declared at most once
@@ -63,6 +73,7 @@ class AirbytePythonPlugin implements Plugin<Project> {
63
73
64
74
void apply (Project project ) {
65
75
def extension = project. extensions. create(' airbytePython' , AirbytePythonConfiguration )
76
+
66
77
def venvDirectoryName = ' .venv'
67
78
project. plugins. apply ' ru.vyarus.use-python'
68
79
@@ -71,34 +82,63 @@ class AirbytePythonPlugin implements Plugin<Project> {
71
82
minPythonVersion = ' 3.7'
72
83
scope = ' VIRTUALENV'
73
84
installVirtualenv = true
74
- pip ' flake8:3.8.4'
75
- pip ' black:21.10b0'
76
- pip ' mypy:0.812'
85
+ pip ' pip:21.3.1'
86
+ pip ' mccabe:0.6.1'
87
+ // flake8 doesn't support pyproject.toml files
88
+ // and thus there is the wrapper "pyproject-flake8" for this
89
+ pip ' pyproject-flake8:0.0.1a2'
90
+ pip ' black:22.1.0'
91
+ pip ' mypy:0.930'
77
92
pip ' isort:5.6.4'
78
93
pip ' pytest:6.1.2'
79
- pip ' pip:21.1.3'
80
94
pip ' coverage[toml]:6.3.1'
81
95
}
82
96
83
97
84
98
project. task(' isortFormat' , type : PythonTask ) {
85
99
module = " isort"
86
- command = " . --settings-file ${ project.rootProject.file('tools/python/.isort.cfg').absolutePath} "
100
+ command = " --settings-file=${ project.rootProject.file('pyproject.toml').absolutePath} ./"
101
+ }
102
+
103
+ project. task(' isortReport' , type : PythonTask ) {
104
+ module = " isort"
105
+ command = " --settings-file=${ project.rootProject.file('pyproject.toml').absolutePath} --diff --quiet ./"
106
+ outputPrefix = ' '
87
107
}
88
108
89
109
project. task(' blackFormat' , type : PythonTask ) {
90
110
module = " black"
91
111
// the line length should match .isort.cfg
92
- command = " . --line-length 140 "
112
+ command = " --config ${ project.rootProject.file('pyproject.toml').absolutePath } ./ "
93
113
dependsOn project. rootProject. licenseFormat
94
114
dependsOn project. isortFormat
95
115
}
96
116
117
+ project. task(' blackReport' , type : PythonTask ) {
118
+ module = " black"
119
+ command = " --config ${ project.rootProject.file('pyproject.toml').absolutePath} --diff --quiet ./"
120
+ outputPrefix = ' '
121
+ }
122
+
97
123
project. task(' flakeCheck' , type : PythonTask , dependsOn : project. blackFormat) {
98
- module = " flake8"
99
- command = " . --config ${ project.rootProject.file('tools/python/.flake8').absolutePath} "
124
+ module = " pflake8"
125
+ command = " --config ${ project.rootProject.file('pyproject.toml').absolutePath} ./"
126
+ }
127
+
128
+ project. task(' flakeReport' , type : PythonTask ) {
129
+ module = " pflake8"
130
+ command = " --exit-zero --config ${ project.rootProject.file('pyproject.toml').absolutePath} ./"
131
+ outputPrefix = ' '
132
+ }
133
+
134
+ project. task(" mypyReport" , type : Exec ){
135
+ commandLine = " .venv/bin/python"
136
+ args " -m" , " mypy" , " --config-file" , " ${ project.rootProject.file('pyproject.toml').absolutePath} " , " ./"
137
+ setIgnoreExitValue true
100
138
}
101
139
140
+
141
+
102
142
// attempt to install anything in requirements.txt. by convention this should only be dependencies whose source is located in the project.
103
143
104
144
if (project. file(' requirements.txt' ). exists()) {
@@ -109,7 +149,7 @@ class AirbytePythonPlugin implements Plugin<Project> {
109
149
outputs. file(' build/installedlocalreqs.txt' )
110
150
111
151
// HACK: makes all integrations depend on installing requirements for bases. long term we should resolve deps and install in order.
112
- if (project. getPath(). startsWith(" :airbyte-integrations:connectors" )) {
152
+ if (project. getPath(). startsWith(" :airbyte-integrations:connectors" ) && ! project . hasProperty( " reports_folder " ) ) {
113
153
dependsOn project. rootProject. getTasksByName(" airbytePythonApply" , true ). findAll { it. project. getPath(). startsWith(" :airbyte-integrations:bases" ) }
114
154
}
115
155
}
@@ -139,6 +179,7 @@ class AirbytePythonPlugin implements Plugin<Project> {
139
179
}
140
180
141
181
Helpers . addTestTaskIfTestFilesFound(project, ' unit_tests' , ' unitTest' , project. installTestReqs)
182
+
142
183
Helpers . addTestTaskIfTestFilesFound(project, ' integration_tests' , ' customIntegrationTests' , project. installTestReqs)
143
184
if (! project. tasks. findByName(' integrationTest' )) {
144
185
project. task(' integrationTest' )
@@ -148,7 +189,7 @@ class AirbytePythonPlugin implements Plugin<Project> {
148
189
if (extension. moduleDirectory) {
149
190
project. task(' mypyCheck' , type : PythonTask ) {
150
191
module = " mypy"
151
- command = " -m ${ extension.moduleDirectory} --config-file ${ project.rootProject.file('tools/python/.mypy.ini ').absolutePath} "
192
+ command = " -m ${ extension.moduleDirectory} --config-file ${ project.rootProject.file('pyproject.toml ').absolutePath} "
152
193
}
153
194
154
195
project. check. dependsOn mypyCheck
@@ -160,6 +201,36 @@ class AirbytePythonPlugin implements Plugin<Project> {
160
201
dependsOn project. flakeCheck
161
202
}
162
203
204
+ project. task(' airbytePythonReport' , type : DefaultTask ) {
205
+ dependsOn project. blackReport
206
+ dependsOn project. isortReport
207
+ dependsOn project. flakeReport
208
+ dependsOn project. mypyReport
209
+ doLast {
210
+ if (project. hasProperty(' reports_folder' )) {
211
+ // Gradles adds some log messages to files and we must remote them
212
+ // examples of these lines:
213
+ // :airbyte-integrations:connectors: ...
214
+ // [python] .venv/bin/python -m black ...
215
+ project. fileTree(project. reports_folder). visit { FileVisitDetails details ->
216
+ project. println " Found the report file: " + details. file. path
217
+ def tempFile = project. file(details. file. path + " .1" )
218
+ details. file. eachLine { line ->
219
+ if ( ! line. startsWith(" :airbyte" ) && ! line. startsWith(" [python]" ) ) {
220
+ tempFile << line + " \n "
221
+ }
222
+ }
223
+ if (! tempFile. exists()) {
224
+ // generate empty file
225
+ tempFile << " \n "
226
+ }
227
+ tempFile. renameTo(details. file)
228
+
229
+ }
230
+ }
231
+ }
232
+ }
233
+
163
234
project. task(' airbytePythonApply' , type : DefaultTask ) {
164
235
dependsOn project. installReqs
165
236
dependsOn project. airbytePythonFormat
@@ -187,5 +258,53 @@ class AirbytePythonPlugin implements Plugin<Project> {
187
258
project. assemble. dependsOn project. airbytePythonApply
188
259
project. assemble. dependsOn project. airbytePythonTest
189
260
project. test. dependsOn project. airbytePythonTest
261
+
262
+ // saves tools reports to a custom folder
263
+ def reportsFolder = project. hasProperty(' reports_folder' ) ? project. reports_folder : ' '
264
+ if ( reportsFolder != ' ' ) {
265
+
266
+ // clean reports folders
267
+ project. file(reportsFolder). deleteDir()
268
+ project. file(reportsFolder). mkdirs()
269
+
270
+
271
+
272
+ project. tasks. blackReport. configure {
273
+ it. logging. addStandardOutputListener(new StandardOutputListener () {
274
+ @Override
275
+ void onOutput (CharSequence charSequence ) {
276
+ project. file(" $reportsFolder /black.diff" ) << charSequence
277
+ }
278
+ })
279
+ }
280
+ project. tasks. isortReport. configure {
281
+ it. logging. addStandardOutputListener(new StandardOutputListener () {
282
+ @Override
283
+ void onOutput (CharSequence charSequence ) {
284
+ project. file(" $reportsFolder /isort.diff" ) << charSequence
285
+ }
286
+ })
287
+ }
288
+
289
+ project. tasks. flakeReport. configure {
290
+ it. logging. addStandardOutputListener(new StandardOutputListener () {
291
+ @Override
292
+ void onOutput (CharSequence charSequence ) {
293
+ project. file(" $reportsFolder /flake.txt" ) << charSequence
294
+ }
295
+ })
296
+ }
297
+
298
+ project. tasks. mypyReport. configure {
299
+ it. logging. addStandardOutputListener(new StandardOutputListener () {
300
+ @Override
301
+ void onOutput (CharSequence charSequence ) {
302
+ project. file(" $reportsFolder /mypy.log" ) << charSequence
303
+ }
304
+ })
305
+ }
306
+
307
+ }
190
308
}
191
309
}
310
+
0 commit comments