Skip to content
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

Dissable plugins when needed #113

Merged
merged 12 commits into from
Feb 14, 2017
Merged

Dissable plugins when needed #113

merged 12 commits into from
Feb 14, 2017

Conversation

scphantm
Copy link

@scphantm scphantm commented Feb 9, 2017

We use pygradle primarily as a documentation system for the moment. Because of this, we have projects that won't be configured for full python development. I began going thru the plugin and basically hardening it against things like the setup.py missing doesn't kill the build, just dissables pygradle, same with other aspects. There are tests here to validate

…gradle for other things. need to merge in master again
# Conflicts:
#	pygradle-plugin/src/integTest/groovy/com/linkedin/gradle/python/plugin/PexIntegrationTest.groovy
#	pygradle-plugin/src/integTest/groovy/com/linkedin/gradle/python/plugin/PythonPluginIntegrationTest.groovy
#	pygradle-plugin/src/integTest/groovy/com/linkedin/gradle/python/plugin/PythonWebApplicationPluginIntegrationTest.groovy
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/extension/PythonDetails.java
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/extension/VirtualEnvironment.java
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/extension/internal/ExecutablePathUtils.java
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/plugin/PythonPlugin.groovy
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/tasks/Flake8Task.groovy
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/tasks/PyTestTask.groovy
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/util/FileSystemUtils.java
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/util/OperatingSystem.java
#	pygradle-plugin/src/main/groovy/com/linkedin/gradle/python/util/internal/pex/PexExecSpecAction.java
#	pygradle-plugin/src/test/groovy/com/linkedin/gradle/python/PythonExtensionTest.groovy
#	pygradle-plugin/src/test/groovy/com/linkedin/gradle/python/extension/PythonDetailsUnixTest.groovy
#	pygradle-plugin/src/test/groovy/com/linkedin/gradle/python/extension/PythonDetailsWindowsTest.groovy
#	pygradle-plugin/src/test/groovy/com/linkedin/gradle/python/util/internal/ExecutablePathUtilsTest.groovy
#	version.properties
@scphantm
Copy link
Author

scphantm commented Feb 9, 2017

i figured out (i think) why appveyor failed, it seems that each version of python gives a slightly different output text and i was gathering that text to do my checks. But this lead to another problem with the code. For whatever reason, in the base plugin, you version lock pip to 7.X. the problem is i have machines where when it creates the initial vm, python puts in pip 9.x, then pygradle attempts to downgrade it to 7. That downgrade typically fails and the whole integration suite fails. Is there a particular reason not to up the version of pip and setuptools to the latest? what about the others, flake8 is rather old, with many of the other libraries.

@zvezdan
Copy link
Member

zvezdan commented Feb 9, 2017

@scphantm There is a reason for pinning the versions of the setup/build/test dependencies. Some packages do not work with higher versions of setuptools or the latest version of flake8 does not support all the versions of Python that we do, ..., etc.

We do currently use some of the higher versions internally then what's in the open-source pygradle.
There's a feature that you could also use for the same purpose:

def pythonExtension = ExtensionUtils.getPythonExtension(project)

pythonExtension.forceVersion('pypi', 'flake8', '2.6.2')
pythonExtension.forceVersion('pypi', 'pytest', '3.0.3')
pythonExtension.forceVersion('pypi', 'pytest-cov', '2.4.0')
pythonExtension.forceVersion('pypi', 'pytest-xdist', '1.15.0')

@scphantm
Copy link
Author

scphantm commented Feb 9, 2017

well, ill roll the pip and setuptools back then. and update these in the table. wish i could figure out why uninstalling 9.0.1 causes it to fail. it shouldn't, i don't get it. but i have the test suite running on 3 machines right now, when those cycles finish i will put up another commit.

how does the rest of my changes look?

@scphantm
Copy link
Author

I just don't get it. This suite works find on my mac, but on my windows, i get this. and it only seems to do it with python 3 because python 3 is whats putting in the newer version of pip. do you think the fix is to do a python version sensitive install? meaning if its python 2, install pip 7.12, but if its 3, install 9?

org.gradle.testkit.runner.UnexpectedBuildFailure: Unexpected build execution failure in C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308 with arguments [build, --stacktrace]

Output:
Flake8 config file exists
:foo:pinRequirements
:foo:createVirtualEnvironment
Already using interpreter C:\myApps\Willie\apps\python3\python.exe
Using base prefix 'C:\\myApps\\Willie\\apps\\python3'
New python executable in C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\Scripts\python.exe
Installing setuptools, pip, wheel...done.
:foo:installLinks
:foo:installSetupRequirements
Install appdirs-1.4.0 ............................................... [SKIPPING]
Install packaging-16.8 .............................................. [SKIPPING]
Install wheel-0.26.0 ................................................ [STARTING]
Install (0:06.507 s) ................................................ [FINISHED]
Install setuptools-19.1.1 ........................................... [STARTING]
Install (0:10.895 s) ................................................ [FINISHED]
Install pip-7.1.2 ................................................... [STARTING]
Processing c:\myapps\willie\code\sda\pygradle\build\ivy-repo\pypi\pip\7.1.2\pip-7.1.2.tar.gz
Building wheels for collected packages: pip
  Running setup.py bdist_wheel for pip: started
  Running setup.py bdist_wheel for pip: finished with status 'done'
  Stored in directory: C:\Users\me\AppData\Local\pip\Cache\wheels\d1\76\94\5da3cc57a0a81e4c21f3b63d541895cb5ced9b4c77a9d61009
Successfully built pip
Installing collected packages: pip
  Found existing installation: pip 9.0.1
    Uninstalling pip-9.0.1:
Exception:
Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\shutil.py", line 538, in move
    os.rename(src, real_dst)
FileNotFoundError: [WinError 3] The system cannot find the path specified: 'c:\\users\\me\\appdata\\local\\temp\\2\\junit3185799783516749308\\foo\\build\\venv\\lib\\site-packages\\pip\\_vendor\\requests\\packages\\urllib3\\packages\\ssl_match_hostname\\__pycache__\\_implementation.cpython-35.pyc' -> 'C:\\Users\\me\\AppData\\Local\\Temp\\2\\pip-bfbhewev-uninstall\\users\\me\\appdata\\local\\temp\\2\\junit3185799783516749308\\foo\\build\\venv\\lib\\site-packages\\pip\\_vendor\\requests\\packages\\urllib3\\packages\\ssl_match_hostname\\__pycache__\\_implementation.cpython-35.pyc'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\site-packages\pip\basecommand.py", line 215, in main
    status = self.run(options, args)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\site-packages\pip\commands\install.py", line 342, in run
    prefix=options.prefix_path,
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\site-packages\pip\req\req_set.py", line 778, in install
    requirement.uninstall(auto_confirm=True)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\site-packages\pip\req\req_install.py", line 754, in uninstall
    paths_to_remove.remove(auto_confirm)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\site-packages\pip\req\req_uninstall.py", line 115, in remove
    renames(path, new_path)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\site-packages\pip\utils\__init__.py", line 267, in renames
    shutil.move(old, new)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\shutil.py", line 552, in move
    copy_function(src, real_dst)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\shutil.py", line 251, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)
  File "C:\Users\me\AppData\Local\Temp\2\junit3185799783516749308\foo\build\venv\lib\shutil.py", line 115, in copyfile
    with open(dst, 'wb') as fdst:
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\me\\AppData\\Local\\Temp\\2\\pip-bfbhewev-uninstall\\users\\me\\appdata\\local\\temp\\2\\junit3185799783516749308\\foo\\build\\venv\\lib\\site-packages\\pip\\_vendor\\requests\\packages\\urllib3\\packages\\ssl_match_hostname\\__pycache__\\_implementation.cpython-35.pyc'
:foo:installSetupRequirements FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':foo:installSetupRequirements'.
> Failed to install pip-7.1.2. Please see above output for reason, or re-run your build using ``gradle -i build`` for additional logging.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':foo:installSetupRequirements'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:74)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:55)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
	at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
	at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
	at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
	at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
	at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:153)
	at org.gradle.internal.Factories$1.create(Factories.java:22)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:150)
	at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:98)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:92)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)
	at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:92)
	at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:83)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
	at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:82)
	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
	at org.gradle.tooling.internal.provider.DaemonBuildActionExecuter.execute(DaemonBuildActionExecuter.java:77)
	at org.gradle.tooling.internal.provider.DaemonBuildActionExecuter.execute(DaemonBuildActionExecuter.java:46)
	at org.gradle.tooling.internal.provider.LoggingBridgingBuildActionExecuter.execute(LoggingBridgingBuildActionExecuter.java:60)
	at org.gradle.tooling.internal.provider.LoggingBridgingBuildActionExecuter.execute(LoggingBridgingBuildActionExecuter.java:34)
	at org.gradle.tooling.internal.provider.ProviderConnection.run(ProviderConnection.java:150)
	at org.gradle.tooling.internal.provider.ProviderConnection.run(ProviderConnection.java:113)
	at org.gradle.tooling.internal.provider.DefaultConnection.getModel(DefaultConnection.java:188)
	at org.gradle.tooling.internal.consumer.connection.CancellableModelBuilderBackedModelProducer.produceModel(CancellableModelBuilderBackedModelProducer.java:54)
	at org.gradle.tooling.internal.consumer.connection.PluginClasspathInjectionSupportedCheckModelProducer.produceModel(PluginClasspathInjectionSupportedCheckModelProducer.java:41)
	at org.gradle.tooling.internal.consumer.connection.CompositeAwareModelProducer.produceModel(CompositeAwareModelProducer.java:62)
	at org.gradle.tooling.internal.consumer.connection.AbstractConsumerConnection.run(AbstractConsumerConnection.java:60)
	at org.gradle.tooling.internal.consumer.DefaultBuildLauncher$1.run(DefaultBuildLauncher.java:89)
	at org.gradle.tooling.internal.consumer.DefaultBuildLauncher$1.run(DefaultBuildLauncher.java:83)
	at org.gradle.tooling.internal.consumer.connection.LazyConsumerActionExecutor.run(LazyConsumerActionExecutor.java:79)
	at org.gradle.tooling.internal.consumer.connection.CancellableConsumerActionExecutor.run(CancellableConsumerActionExecutor.java:45)
	at org.gradle.tooling.internal.consumer.connection.ProgressLoggingConsumerActionExecutor.run(ProgressLoggingConsumerActionExecutor.java:58)
	at org.gradle.tooling.internal.consumer.connection.RethrowingErrorsConsumerActionExecutor.run(RethrowingErrorsConsumerActionExecutor.java:38)
	at org.gradle.tooling.internal.consumer.async.DefaultAsyncConsumerActionExecutor$1$1.run(DefaultAsyncConsumerActionExecutor.java:55)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: com.linkedin.gradle.python.tasks.PipInstallTask$PipInstallException: Failed to install pip-7.1.2. Please see above output for reason, or re-run your build using ``gradle -i build`` for additional logging.
	at com.linkedin.gradle.python.tasks.PipInstallTask.pipInstall(PipInstallTask.groovy:185)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:133)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:126)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:115)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:623)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:606)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
	... 62 more


BUILD FAILED

Total time: 55.581 secs

	at org.gradle.testkit.runner.internal.DefaultGradleRunner$1.execute(DefaultGradleRunner.java:222)
	at org.gradle.testkit.runner.internal.DefaultGradleRunner$1.execute(DefaultGradleRunner.java:219)
	at org.gradle.testkit.runner.internal.DefaultGradleRunner.run(DefaultGradleRunner.java:282)
	at org.gradle.testkit.runner.internal.DefaultGradleRunner.build(DefaultGradleRunner.java:219)
	at com.linkedin.gradle.python.plugin.PexIntegrationTest.can build fat pex(PexIntegrationTest.groovy:108)

@scphantm
Copy link
Author

Well, if nothing else, the error is correct, the file its asking for doesn't exist. the only file in that folder is "init.cpython-35.pyc"

@scphantm
Copy link
Author

@ethankhall my file not found error looks exactly like the one we encountered before with your windows merge. whats really weird is that appveyor worked. When the test creates the initial venv, is it using the exe's from the shim or are there full installations of 3 different versions of python on the appveyor machine. Im really beginning to think its a python 3.5 issue as my windows machines don't have 2.X installed at all, only 3.5 and my macs system default is python 2.7

@scphantm
Copy link
Author

@ethankhall , unfortunately, i found it. same file and everything, and sure enough, my path is 263 characters long

pypa/pip#3055

I've been working on this for 20 hours straight, time for some sleep. I guess we have to change the test framework to use a different temp dir when it runs. shouldn't be horribly difficult, but, Tomorrows problem.

…lso implemented a way to assign a pip.conf file to a venv so you can redirect pip on a per project, or global project basis to an internal pypi server. Still having windows problems, pip won't pick up the config file for some reason, but i want to see what citravis does with this code, maybe its not me
@scphantm
Copy link
Author

Ok, i had to redo the base project test routines to get them to create a temp folder in a location other than the OS temp folder. Can't really pass parameters to the TemporaryFolder's constructor the way it was setup so i had to abstract it out. but if its windows, it will create the temporary folders in c:\tmp instead of the system temp. This solved the problem of file names exceeding 260 chars (for now). Windows 10 sorta breaks that barrier down but it won't apply to this because the win10 fix only works on managed applications. this isn't managed.

I also encountered a big problem with pip. it seems for some reason, occasionally, but not all the time, pip decided it needs to go download setuputils-scm off of pipy.python.org. In my network, that site has a hard block on it. Nothing can get to it, even thru the proxy so the test failed. So I need to set the pip.ini (or pip.conf on unix) to point to our internal server. I put in code and configuration settings that allow you to configure the pip.conf on a per project basis, or if the pip.conf is present, then apparently is spills over to the host OS's pip.conf. I have all of this configured to test and for the life of me I can't get pip to pick up the files. I have read the source of pip and it looks right, my only thought is it may be something to do with such an old version of pip on python 35, which is what i am running. What makes it even weirder is when i go into the pip task and hard code an invalid pypi url with the index-url parameter, it stops attempting to go out of the network all together and works just fine. I'm baffled.

Last one is speed. i know windows is slower than linux for files, i get it. but this project now takes 45 minutes to build on my machine. between 6 - 8 minutes for each of the integration tests. Nearly all of that time is spent installing packages into the venv. Does anyone have any ideas how to speed that up?

this.details = new PythonDetails(project)
docsDir = Paths.get(project.projectDir.absolutePath, "docs").toFile().path
testDir = Paths.get(project.projectDir.absolutePath, "test").toFile().path
srcDir = Paths.get(project.projectDir.absolutePath, "src").toFile().path
setupCfg = Paths.get(project.projectDir.absolutePath, "setup.cfg").toFile().path

// creating a flake8 config file if one doesn't exist, this prevents "file not found" issues.
def cfgCheck = project.file(setupCfg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do work in configuration time. If you want this, pull it into a task that flake8 depends on.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done (post just to keep tasks tracked in my head)

import org.gradle.api.tasks.TaskAction


class CleanSaveVenvTask extends DefaultTask {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're attempting to move to Java 7 from Groovy (speed and type safety). Can you move this to Java?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want it in the src/java or src/groovy folder. seems everyone has a preference now adays.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really care but looking at the project structure src/main/groovy would probably be most consistent with what we have now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done (post just to keep tasks tracked in my head) also added a unit test to run it as well

import com.linkedin.gradle.python.extension.PythonDetails
import com.linkedin.gradle.python.tasks.execution.FailureReasonProvider
import com.linkedin.gradle.python.tasks.execution.TeeOutputContainer
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import org.apache.tools.ant.taskdefs.condition.Os
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use this. Use our OperatingSystem class.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

fileExtension = "conf"
}

File pip = new File(Paths.get(pythonDetails.getVirtualEnv().absolutePath, "pip.${fileExtension}").toString())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Paths.get(pythonDetails.getVirtualEnv(), "pip.${fileExtension}").toFile().getAbsoluteFile()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. added unit test to verify creation of the pip file as well

def pyVersion = pythonDetails.getPythonVersion().pythonMajorMinor
def extension = ExtensionUtils.getPythonExtension(project)
def sitePackages = findSitePackages()

for (File installable : getConfigurationFiles()) {
if (isReadyForInstall(installable)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What problem are you trying to solve here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use this plugin for python projects (yet, thats phase 2) phase 1 is to enable sphinx documentation for our java, c#, Javascript, and sql projects, several hundred of them. So for a java project that has nothing to do with python, we can't have the plugin fail because it couldn't find a python project. This method is looking to see if pip is getting ready to install the python project itself. If it is, is it properly configured (setup.py exists and such)? If its not properly configured, we throw a warning and move on instead of blow up the build.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you writing your own plugin on top pygradle to do this? If so I would just disable all the tasks that aren't specifically needed for Sphinx.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, i have a very thin wrapper that is simply setting some default configuration settings. thats it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Thinking about it, this is probably a pretty useful use case that we solve (docs across languages are hard). I know earlier you proposed making a Sphinx plugin would you be up to doing that? Then you could disable all the things that you don't need to optimize this use case. I would probably still apply the python plugin then configure it to make it fast.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can certainly try. are you opposed to me adding https://github.com/dorongold/gradle-task-tree to help in deconstructing the task graph? If you have major concerns with it, i can put it in for development and pull it out before you merge.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at breaking this up a little closer, that is a big deal, lots of testing, lots of regression testing, lots of ways to screw it up. Lets get this PR kosher and merged, then I will create a second PR to tackle splitting off Sphinx. Trying to do both is a bit much for one PR in my opinion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a plan!

@@ -36,21 +37,33 @@ class PyTestTask extends AbstractPythonTestSourceDefaultTask {
ignoreExitValue = true
}

def dissableTests() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do this as Task.onlyIf(), so the task doesn't even execute.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

PythonExtension pythonExtension = project.extensions.getByName("python") as PythonExtension

Map<String, Map<String, String>> pipConfig = pythonExtension.pipConfig

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you refactor this out into a class so a test can be written for it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the config or the whole feature? Im still having problems getting pip to read the file for some reason too. I'm beginning to think its the combination of pip 7.X with python 3.5 that im running is whats screwing me up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the writing out the config file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, pulled it out to a java class, previous test still checks it.

project.logger.info("Flake8: testDir doesn't exist")
}

if (paths.size() > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Task.onlyIf() here too.

Copy link
Author

@scphantm scphantm Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but there was a complication. Narc complained that the PythonPluggins class went over 350 lines (352 to be exact). So to make it smaller, I tried moving the constants to an interface. Been doing that for 15 years now. Apparently, thats not considered a good design pattern anymore cuz Narc complained about that. Turns out, for big lists of constants like that the prefered pattern is an Enum. So i had to convert everything to an enum and update the codebase. When I do the Sphinx conversion, I will split this file up into sub classes. I did it with another plugin I have, its more planning than work. When i do that, i can convert things back to string constants if you want because i will have the room in the file. Otherwise, when doing that conversion I will further refine the Enum. Its a single enum at the moment, really should be 3 or 4. (tasks, groups, directories, etc)

List<String> sArgs = [pythonDetails.virtualEnvironment.findExecutable("flake8").absolutePath,
"--config", component.setupCfg]

if (!project.file(pythonDetails.virtualEnvironment.findExecutable("flake8").absolutePath).exists()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this if-check for? Why would flake8 not be installed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was very strange, i was getting integration tests that were failing with a "file not found". started putting more and more checks into figure out what it coudn't find and magically started working. i can start pulling some of that out and see if it breaks again

*/
package com.linkedin.gradle.python.plugin.testutils

import org.apache.tools.ant.taskdefs.condition.Os
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the OperatingSystem class here too.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Copy link
Contributor

@ethankhall ethankhall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking really good, a few small things but if you get them done I'll merge it in.

Thanks for the contribution!

@@ -132,7 +137,7 @@ class PythonExtension {
forceVersion(split[0], split[1], split[2])
}

public PythonDetails getDetails() {
PythonDetails getDetails() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets leave these methods as public. We use them internally.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i reverted all of them back

def pyVersion = pythonDetails.getPythonVersion().pythonMajorMinor
def extension = ExtensionUtils.getPythonExtension(project)
def sitePackages = findSitePackages()

for (File installable : getConfigurationFiles()) {
if (isReadyForInstall(installable)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a plan!

@@ -108,6 +108,10 @@ public void args(String... args) {
arguments.addAll(Arrays.asList(args));
}

public void args(List<String> args) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? Shouldn't args(Collection) handle this?

if (!specificFileGiven) {
args(component.testDir)
}
// if (!project.file(component.testDir).exists()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove these commented out lines, and the commented out method too.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NP

@ethankhall ethankhall merged commit 0f98f9a into linkedin:master Feb 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants