python.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package buildpacks
  2. import (
  3. "fmt"
  4. "strings"
  5. "sync"
  6. "github.com/google/go-github/github"
  7. )
  8. type pythonRuntime struct {
  9. wg sync.WaitGroup
  10. }
  11. func NewPythonRuntime() Runtime {
  12. return &pythonRuntime{}
  13. }
  14. func (runtime *pythonRuntime) detectPipenv(results chan struct {
  15. string
  16. bool
  17. }, directoryContent []*github.RepositoryContent) {
  18. pipfileFound := false
  19. pipfileLockFound := false
  20. for i := 0; i < len(directoryContent); i++ {
  21. name := directoryContent[i].GetName()
  22. if name == "Pipfile" {
  23. pipfileFound = true
  24. } else if name == "Pipfile.lock" {
  25. pipfileLockFound = true
  26. }
  27. if pipfileFound && pipfileLockFound {
  28. break
  29. }
  30. }
  31. if pipfileFound && pipfileLockFound {
  32. results <- struct {
  33. string
  34. bool
  35. }{pipenv, true}
  36. }
  37. runtime.wg.Done()
  38. }
  39. func (runtime *pythonRuntime) detectPip(results chan struct {
  40. string
  41. bool
  42. }, directoryContent []*github.RepositoryContent) {
  43. requirementsTxtFound := false
  44. for i := 0; i < len(directoryContent); i++ {
  45. name := directoryContent[i].GetName()
  46. if name == "requirements.txt" {
  47. requirementsTxtFound = true
  48. }
  49. }
  50. if requirementsTxtFound {
  51. results <- struct {
  52. string
  53. bool
  54. }{pip, true}
  55. }
  56. runtime.wg.Done()
  57. }
  58. func (runtime *pythonRuntime) detectConda(results chan struct {
  59. string
  60. bool
  61. }, directoryContent []*github.RepositoryContent) {
  62. environmentFound := false
  63. packageListFound := false
  64. for i := 0; i < len(directoryContent); i++ {
  65. name := directoryContent[i].GetName()
  66. if name == "environment.yml" {
  67. environmentFound = true
  68. break
  69. } else if name == "package-list.txt" {
  70. packageListFound = true
  71. break
  72. }
  73. }
  74. if environmentFound || packageListFound {
  75. results <- struct {
  76. string
  77. bool
  78. }{conda, true}
  79. }
  80. runtime.wg.Done()
  81. }
  82. func (runtime *pythonRuntime) detectStandalone(results chan struct {
  83. string
  84. bool
  85. }, directoryContent []*github.RepositoryContent) {
  86. pyFound := false
  87. for i := 0; i < len(directoryContent); i++ {
  88. name := directoryContent[i].GetName()
  89. if strings.HasSuffix(name, ".py") {
  90. pyFound = true
  91. break
  92. }
  93. }
  94. if pyFound {
  95. results <- struct {
  96. string
  97. bool
  98. }{standalone, true}
  99. }
  100. runtime.wg.Done()
  101. }
  102. func (runtime *pythonRuntime) Detect(
  103. client *github.Client,
  104. directoryContent []*github.RepositoryContent,
  105. owner, name, path string,
  106. repoContentOptions github.RepositoryContentGetOptions,
  107. paketo, heroku *BuilderInfo,
  108. ) error {
  109. results := make(chan struct {
  110. string
  111. bool
  112. }, 4)
  113. fmt.Printf("Starting detection for a Python runtime for %s/%s\n", owner, name)
  114. runtime.wg.Add(4)
  115. fmt.Println("Checking for pipenv")
  116. go runtime.detectPipenv(results, directoryContent)
  117. fmt.Println("Checking for pip")
  118. go runtime.detectPip(results, directoryContent)
  119. fmt.Println("Checking for conda")
  120. go runtime.detectConda(results, directoryContent)
  121. fmt.Println("Checking for Python standalone")
  122. go runtime.detectStandalone(results, directoryContent)
  123. runtime.wg.Wait()
  124. close(results)
  125. paketoBuildpackInfo := BuildpackInfo{
  126. Name: "Python",
  127. Buildpack: "paketobuildpacks/python",
  128. }
  129. herokuBuildpackInfo := BuildpackInfo{
  130. Name: "Python",
  131. Buildpack: "heroku/python",
  132. }
  133. if len(results) == 0 {
  134. fmt.Printf("No Python runtime detected for %s/%s\n", owner, name)
  135. paketo.Others = append(paketo.Others, paketoBuildpackInfo)
  136. heroku.Others = append(heroku.Others, herokuBuildpackInfo)
  137. return nil
  138. }
  139. paketo.Detected = append(paketo.Detected, paketoBuildpackInfo)
  140. heroku.Detected = append(heroku.Detected, herokuBuildpackInfo)
  141. return nil
  142. }