/devtools/conda-envs/generate_envs.py

https://github.com/MolSSI/QCFractal · Python · 146 lines · 115 code · 15 blank · 16 comment · 10 complexity · 681569b74f90596ede962164c33623ed MD5 · raw file

  1. """
  2. Automatically generates the QCArchive environments
  3. """
  4. import copy
  5. from ruamel.yaml import YAML
  6. yaml = YAML()
  7. yaml.indent(mapping=2, sequence=2, offset=2)
  8. template = """
  9. name: qcarchive
  10. channels:
  11. - defaults
  12. - conda-forge
  13. dependencies:
  14. - pip
  15. # Core dependencies
  16. - msgpack-python >=0.6.1
  17. - numpy
  18. - pyyaml >=5.1
  19. - pydantic >=1.4.0
  20. - requests
  21. - tornado
  22. # Security dependencies
  23. - bcrypt
  24. - cryptography
  25. # Storage dependencies
  26. - alembic
  27. - psycopg2 >=2.7
  28. - postgresql
  29. - sqlalchemy >=1.3
  30. # QCPortal dependencies
  31. - double-conversion >=3.0.0
  32. - h5py
  33. - pandas
  34. - plotly >=4.0.0
  35. - pyarrow >=0.15.0
  36. - tqdm
  37. # Test depends
  38. - codecov
  39. - pytest
  40. - pytest-cov
  41. - requests-mock
  42. """
  43. qca_ecosystem_template = ["qcengine >=0.17.0", "qcelemental >=0.17.0"]
  44. pip_depends_template = []
  45. def generate_yaml(filename=None, channels=None, dependencies=None, pip_dependencies=None, qca_ecosystem=None):
  46. """
  47. Builds out a specific template, quite limited in scope.
  48. """
  49. if filename is None:
  50. raise KeyError("Must have a filename")
  51. # Handle channels
  52. env = yaml.load(template)
  53. if channels is not None:
  54. for c in channels:
  55. env["channels"].insert(1, c)
  56. offset = len(env["channels"])
  57. env["channels"].yaml_set_comment_before_after_key(offset, before="\n")
  58. # General conda depends
  59. if dependencies is not None:
  60. offset = len(env["dependencies"])
  61. env["dependencies"].yaml_set_comment_before_after_key(offset, before="\n Environment specific includes")
  62. env["dependencies"].extend(dependencies)
  63. # Add in QCArchive ecosystem
  64. offset = len(env["dependencies"])
  65. env["dependencies"].yaml_set_comment_before_after_key(offset, before="\n QCArchive includes")
  66. if qca_ecosystem is None:
  67. env["dependencies"].extend(qca_ecosystem_template)
  68. else:
  69. env["dependencies"].extend(qca_ecosystem)
  70. # Add in pip
  71. pip_env = copy.deepcopy(pip_depends_template)
  72. if pip_dependencies is not None:
  73. pip_env.extend(pip_dependencies)
  74. if len(pip_env):
  75. offset = len(env["dependencies"])
  76. env["dependencies"].yaml_set_comment_before_after_key(offset, before="\n Pip includes")
  77. env["dependencies"].extend([{"pip": pip_env}])
  78. with open(filename, "w") as handle:
  79. yaml.dump(env, handle)
  80. environs = [
  81. {
  82. # No extra dependancies, the base env
  83. "filename": "base.yaml",
  84. },
  85. {
  86. # Tools to test out dask adapter
  87. "filename": "adapter_dask.yaml",
  88. "dependencies":
  89. ["rdkit", "dask", "distributed", "dask-jobqueue >=0.5.0"],
  90. },
  91. {
  92. # Tools to test out parsl adapter
  93. "filename": "adapter_parsl.yaml",
  94. "dependencies":
  95. ["rdkit", "ipyparallel", "ipykernel", "parsl >=0.9.0"],
  96. },
  97. {
  98. # Tools to test out fireworks adapter
  99. "filename": "adapter_fireworks.yaml",
  100. "pip_dependencies": ["fireworks"]
  101. },
  102. {
  103. # Tests for the OpenFF toolchain (geometric and torsiondrive)
  104. "filename": "openff.yaml",
  105. "channels": ["psi4/label/dev", "omnia"],
  106. "dependencies": ["psi4>1.4a2.dev700,<1.4a2", "rdkit", "geometric >=0.9.3", "torsiondrive", "dftd3",
  107. "openforcefield >=0.7.1", "openforcefields >=1.2.0", "openmm >=7.4.2",
  108. "openmmforcefields >=0.8.0"
  109. ],
  110. },
  111. {
  112. # Tests for the current development heads
  113. "filename":
  114. "dev_head.yaml",
  115. "dependencies": ["rdkit"],
  116. "qca_ecosystem": [],
  117. "pip_dependencies": [
  118. "git+git://github.com/MolSSI/QCEngine#egg=qcengine",
  119. "git+git://github.com/MolSSI/QCElemental#egg=qcelemental",
  120. "git+git://github.com/leeping/geomeTRIC#egg=geometric",
  121. "git+git://github.com/lpwgroup/torsiondrive.git#egg=torsiondrive",
  122. ] # yapf: disable
  123. }
  124. ]
  125. for envdata in environs:
  126. generate_yaml(**envdata)