# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['cp2k_input_tools', 'cp2k_input_tools.cli']

package_data = \
{'': ['*'], 'cp2k_input_tools': ['templates/*']}

install_requires = \
['Jinja2>=2.11.3,<4.0.0',
 'click>=7.1.2,<9',
 'pint>=0.15,<0.18',
 'pydantic>=1.8.2,<2.0.0',
 'transitions>=0.7,<0.8']

extras_require = \
{':python_version >= "3.6" and python_version < "3.7"': ['dataclasses>=0.7,<1'],
 'lsp': ['pygls>=0.10,<0.12'],
 'yaml': ['ruamel.yaml>=0.16.5,<0.18.0']}

entry_points = \
{'console_scripts': ['cp2k-datafile-lint = '
                     'cp2k_input_tools.cli.datafile_lint:cp2k_datafile_lint',
                     'cp2k-language-server = '
                     'cp2k_input_tools.cli.lsp:cp2k_language_server',
                     'cp2kgen = cp2k_input_tools.cli.cp2kgen:cp2kgen',
                     'cp2kget = cp2k_input_tools.cli.cp2kget:cp2kget',
                     'cp2klint = cp2k_input_tools.cli.lint:cp2klint',
                     'fromcp2k = cp2k_input_tools.cli.fromcp2k:fromcp2k',
                     'tocp2k = cp2k_input_tools.cli.tocp2k:tocp2k']}

setup_kwargs = {
    'name': 'cp2k-input-tools',
    'version': '0.8.1',
    'description': 'Python tools to handle CP2K input files',
    'long_description': '# cp2k-input-tools\n\n[![Build status](https://github.com/cp2k/cp2k-input-tools/actions/workflows/test.yml/badge.svg)](https://github.com/cp2k/cp2k-input-tools/actions) [![codecov](https://codecov.io/gh/cp2k/cp2k-input-tools/branch/develop/graph/badge.svg)](https://codecov.io/gh/cp2k/cp2k-input-tools) [![PyPI](https://img.shields.io/pypi/pyversions/cp2k-input-tools)](https://pypi.org/project/cp2k-input-tools/)\n\nFully validating pure-python CP2K input file parsers including preprocessing capabilities\n\nAvailable commands (also available through an API, see below):\n\n* `cp2klint` .. a CP2K input file linter\n* `fromcp2k` .. create a JSON/YAML configuration file or an [AiiDA](https://github.com/aiidateam/aiida-cp2k) run script from a CP2K input file (includes validation)\n* `tocp2k` .. convert a JSON or YAML configuration back to CP2K\'s input file format (includes validation)\n* `cp2kgen` .. generate new input files based on a given input file and expressions to change parameters programmatically\n* `cp2kget` .. get values from a CP2K input file (most likely a restart file) given a path of sections and attribute\n* `cp2k-language-server` .. a [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) implementation for the CP2K input file format\n* `cp2k-datafile-lint` .. linters for other CP2K-related data file formats (like pseudos and basissets)\n\nFor a description of the JSON/YAML formats used, see below.\n\n## Requirements\n\n* Python 3.6+\n* https://pypi.org/project/transitions/\n* https://pypi.org/project/pint/\n* optional: https://pypi.org/project/ruamel.yaml/ for YAML support\n* optional: https://github.com/openlawlibrary/pygls for the cp2k-language-server\n\nFor development: https://poetry.eustace.io/ https://pytest.org/\n\n## Idea\n\n* have a pure-python CP2K input file linter with proper syntax error reporting (context, etc.)\n* a final & complete restart file parser\n* basis for an AiiDA CP2K project importer\n* testbed for alternative import formats (YAML, JSON) for CP2K\n* possible testbed for a re-implementation of the CP2K input parser itself\n\n## TODOs\n\n* parser: improve error reporting with context\n* preprocessor: don\'t lose original context when interpolating variables\n* parser: parsing the XML is slow (easily 70% of the time), pickle or generate Python code directly instead and keep XML parsing as fallback\n* parser: preserve comments when going to/from YAML\n\n# Usage\n\n## Installation\n\nYou will get most tools using simply:\n\n```console\n$ pip install cp2k-input-tools\n```\n\nFor YAML support you should use\n\n```console\n$ pip install cp2k-input-tools[yaml]\n```\n\nand for the Language Server:\n\n```console\n$ pip install cp2k-input-tools[lsp]\n```\n\n## Command Line Interface\n\nGenerate JSON, YAML or aiida-cp2k run script from a CP2K input file:\n\n```console\n$ fromcp2k --help\nusage: fromcp2k [-h] [-y] [-c] [-b BASE_DIR] [-t TRAFO] <file>\n\nConvert CP2K input to JSON (default) or YAML\n\npositional arguments:\n  <file>                CP2K input file\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -y, --yaml            output yaml instead of json\n  -c, --canonical       use the canonical output format\n  -b BASE_DIR, --base-dir BASE_DIR\n                        search path used for relative @include\'s\n  -t TRAFO, --trafo TRAFO\n                        transformation applied to key and section names (auto,\n                        upper, lower)\n```\n\nGenerate an [aiida-cp2k](https://github.com/aiidateam/aiida-cp2k) template run script:\n\n```console\n$ fromcp2k --format aiida-cp2k-calc tests/inputs/test01.inp\nAny key transformation function other than \'auto\' is ignored when generating an aiida-cp2k run script template\n\nfrom aiida.engine import run\nfrom aiida.orm import (load_code, Dict, StructureData)\n\ncp2k_code = load_code(\'...\')\n\n# Structure\nstructure = StructureData(...)\n\n# Parameters\nparameters = Dict(\n    dict={\n           "FORCE_EVAL": {\n               "DFT": {\n                   "KPOINTS": {\n                       "FULL_GRID": False,\n                       "PARALLEL_GROUP_SIZE": -1,\n                       "SCHEME": "MONKHORST-PACK 3 3 3",\n                       "SYMMETRY": False,\n                   },\n                   "MGRID": {\n                       "CUTOFF": 1000.0,\n                       "REL_CUTOFF": 100.0,\n                   },\n                   "POISSON": {\n                       "PERIODIC": "XYZ",\n                   },\n                   "PRINT": {\n                       "OVERLAP_CONDITION": {\n                           "_": "ON",\n                           "1-NORM": True,\n                           "DIAGONALIZATION": True,\n                       },\n                   },\n                   "QS": {\n                       "EPS_DEFAULT": 1e-16,\n                       "EXTRAPOLATION": "USE_GUESS",\n                       "METHOD": "GAPW",\n                   },\n                   "SCF": {\n                       "SMEAR": {\n                           "_": True,\n                           "ELECTRONIC_TEMPERATURE": 300.0,\n                           "METHOD": "FERMI_DIRAC",\n                       },\n                       "ADDED_MOS": 40,\n                       "EPS_SCF": 1e-08,\n                       "MAX_SCF": 50,\n                   },\n                   "XC": {\n                       "XC_FUNCTIONAL": {\n                           "_": "PBE",\n                       },\n                   },\n                   "BASIS_SET_FILE_NAME": "./BASIS_SETS",\n                   "POTENTIAL_FILE_NAME": "./POTENTIALS",\n               },\n               "SUBSYS": {\n                   "CELL": {\n                       "CELL_REF": {\n                           "A": "4.32947291598 0.0 0.0",\n                           "B": "2.16473645799 3.7494335304 0.0",\n                           "C": "2.16473645799 1.24981118034 3.53499983838",\n                           "PERIODIC": "XYZ",\n                       },\n                       "A": "4.07419 0.0 0.0",\n                       "B": "2.037095 3.52835204 0.0",\n                       "C": "2.037095 1.17611735 3.32656221",\n                       "PERIODIC": "XYZ",\n                   },\n                   "KIND": [\n                       {\n                       "_": "Ge",\n                       "ELEMENT": "Ge",\n                       "POTENTIAL": "ALL-q32",\n                       "BASIS_SET": "ORB pob-TZVP",\n                       },\n                   ],\n                   "TOPOLOGY": {\n                       "COORD_FILE_NAME": "./struct.xyz",\n                       "COORD_FILE_FORMAT": "XYZ",\n                   },\n               },\n               "METHOD": "QUICKSTEP",\n           },\n           "GLOBAL": {\n               "PRINT_LEVEL": "MEDIUM",\n               "PROJECT_NAME": "fatman.calc",\n               "RUN_TYPE": "ENERGY",\n           },\n    })\n\n# Construct process builder.\nbuilder = cp2k_code.get_builder()\nbuilder.structure = structure\nbuilder.parameters = parameters\nbuilder.code = cp2k_code\nbuilder.metadata.options.resources = {\n    "num_machines": 1,\n    "num_mpiprocs_per_machine": 1,\n}\nbuilder.metadata.options.max_wallclock_seconds = 1 * 3 * 60\n\nrun(builder)\n```\n\n\nGenerate a CP2K input file from a JSON or YAML:\n\n```console\n$ tocp2k --help\nusage: tocp2k [-h] [-y] <file>\n\nConvert JSON or YAML input to CP2K\n\npositional arguments:\n  <file>      JSON or YAML input file\n\noptional arguments:\n  -h, --help  show this help message and exit\n  -y, --yaml\n```\n\nLint a CP2K input file:\n\n```console\n$ cp2klint tests/inputs/unterminated_var.inp\nSyntax error: unterminated variable, in tests/inputs/unterminated_var.inp:\nline   36: @IF ${HP\n               ~~~~^\n```\n\nGenerate input files for a `CUTOFF` convergence study (multiple expressions will be combined as a cartesian product):\n\n```console\n$ cp2kgen tests/inputs/NaCl.inp "force_eval/dft/mgrid/cutoff=[800,900,1000]"\nWriting \'NaCl-cutoff_800.inp\'...\nWriting \'NaCl-cutoff_900.inp\'...\nWriting \'NaCl-cutoff_1000.inp\'...\n$ diff -Naurb NaCl-cutoff_800.inp NaCl-cutoff_900.inp\n--- NaCl-cutoff_800.inp\t2019-10-21 18:52:09.994323474 +0200\n+++ NaCl-cutoff_900.inp\t2019-10-21 18:52:10.680996641 +0200\n@@ -69,7 +69,7 @@\n       POTENTIAL_FILE_NAME ALL_POTENTIALS\n       &MGRID\n          REL_CUTOFF 80.0\n-         CUTOFF 800\n+         CUTOFF 900\n          NGRIDS 6\n       &END MGRID\n       &XC\n```\n\nGet a value from a CP2K input file, for example a `RESTART` file generated in a cell optimization:\n\n```console\n$ cp2kget tests/inputs/NaCl.inp "force_eval/subsys/cell/a/0"\nforce_eval/subsys/cell/a/0: 5.64123539364476\n```\n\n## API\n\nConvert a CP2K input file to a nested Python dictionary:\n\n```python\nfrom cp2k_input_tools.parser import CP2KInputParser, CP2KInputParserSimplified\n\ncanonical = False\n\nif canonical:\n    parser = CP2KInputParser()\nelse:\n    parser = CP2KInputParserSimplified()\n\nwith open("project.inp") as fhandle:\n    tree = parser.parse(fhandle)\n```\n\nConvert a nested Python dictionary back to a CP2K input file:\n\n```python\nfrom cp2k_input_tools.generator import CP2KInputGenerator\n\ngenerator = CP2KInputGenerator()\n\ntree = {"global": {}}  # ... the input tree\n\nwith open("project.inp", "w") as fhandle:\n    for line in generator.line_iter(tree):\n        fhandle.write(f"{line}\\n")\n```\n\n## Language Server Protocol\n\nThe executable providing the language server is: `cp2k-language-server`\n\nFor `vim` you need a plugin to be able to use language servers. One such plugin is [ALE](https://github.com/dense-analysis/ale) for which you can create in its directory the file `ale_linters/cp2k/language_server.vim` with the content\n\n```vim\ncall ale#Set(\'cp2k_lsp_executable\', \'cp2k-language-server\')\n\nfunction! ale_linters#cp2k#language_server#GetProjectRoot(buffer) abort\n    let l:git_path = ale#path#FindNearestDirectory(a:buffer, \'.git\')\n\n    return !empty(l:git_path) ? fnamemodify(l:git_path, \':h:h\') : \'\'\nendfunction\n\ncall ale#linter#Define(\'cp2k\', {\n\\   \'name\': \'language_server\',\n\\   \'lsp\': \'stdio\',\n\\   \'executable\': {b -> ale#Var(b, \'cp2k_lsp_executable\')},\n\\   \'project_root\': function(\'ale_linters#cp2k#language_server#GetProjectRoot\'),\n\\   \'command\': \'%e\',\n\\})\n```\nAfterwards you must set the filetype when editing a CP2K input file to `cp2k` to get it running. This can be done explicitly using `:set filetype=cp2k`.\n\n\n# The CP2K JSON and YAML formats\n\nA reference to the CP2K input format can be found here: https://manual.cp2k.org/\n\n## Canonical format\n\nFor everything except the pre-processor capabilities (`@IF/@ENDIF/$var/@SET`) there is a canonical one-to-one mapping of the CP2K input format to either JSON or YAML:\n\n* repeatable sections are mapped to dictionaries\n* keywords or subsections are key/value entries in sections\n* all repeatable elements (sections and keywords) are mapped to lists of their respective mapped datatype\n* section parameters are mapped to a special key named `_`\n* default section keywords are mapped to a special key name `*`\n* sections in JSON or YAML must be prefixed to avoid double definition of a key in case of same name for a section and a keyword (like the `POTENTIAL` in `KIND`), to avoid quotation marks, instead of CP2K\'s `&` we are using the `+`\n* keyword values are mapped based on their datatypes: a list of values is always mapped to a list of their respective datatypes\n\nThe following example input:\n\n```\n&GLOBAL\n   PRINT_LEVEL MEDIUM\n   PROJECT test\n   RUN_TYPE ENERGY\n&END GLOBAL\n&FORCE_EVAL\n   METHOD Quickstep\n   &DFT\n      BASIS_SET_FILE_NAME "./BASIS_SETS"\n      POTENTIAL_FILE_NAME ./POTENTIALS\n      &XC\n         &XC_FUNCTIONAL PBE\n         &END XC_FUNCTIONAL\n      &END XC\n   &END DFT\n   &SUBSYS\n      &CELL\n         A [angstrom] 4.07419 0.0 0.0\n         B [angstrom] 2.037095 3.52835204 0.0\n         C [angstrom] 2.037095 1.17611735 3.32656221\n         PERIODIC XYZ\n      &END CELL\n      &KIND Ge\n         ELEMENT Ge\n         POTENTIAL ALL-q32\n         BASIS_SET ORB pob-TZVP\n      &END KIND\n      &TOPOLOGY\n         COORD_FILE ./struct.xyz\n         COORD_FILE_FORMAT XYZ\n      &END TOPOLOGY\n   &END SUBSYS\n&END FORCE_EVAL\n```\n\nwould generate the (canonical) JSON:\n\n```json\n{\n  "+global": {\n    "print_level": "medium",\n    "project_name": "test",\n    "run_type": "energy"\n  },\n  "+force_eval": [\n    {\n      "method": "quickstep",\n      "+DFT": {\n        "basis_set_file_name": [\n          "./BASIS_SETS"\n        ],\n        "potential_file_name": "./POTENTIALS"\n      },\n      "+XC": {\n        "+xc_functional": {\n          "_": "PBE"\n        }\n      },\n      "+subsys": {\n        "cell": {\n          "A": [ 4.07419, 0, 0 ],\n          "B": [ 2.037095, 3.52835204, 0 ],\n          "C": [ 2.037095, 1.17611735, 3.32656221 ],\n          "periodic": "XYZ"\n        },\n        "+kind": [\n          {\n            "_": "Ge",\n            "element": "Ge",\n            "potential": "ALL-q32",\n            "basis_set": [\n              [ "ORB", "pob-TZVP" ]\n            ]\n          }\n          ],\n        "+topology": {\n          "coord_file_name": "./struct.xyz",\n          "coord_file_format": "XYZ"\n        }\n      }\n    }\n  ]\n}\n```\n\n*Caveats*:\n\n* the full input format needs be known and is being loaded from a bundled `cp2k_input.xml`\n* the YAML/JSON is quiet verbose and one has to know exactly which keywords can be repeated\n\nWhile there is no solution to remedy the first caveat, the second can be solved with the simplified output format\n\n## Simplified format\n\nStill based on the canonical format the simplified format relaxes some of the rules\n\n1. a section must only be prefixed with a `+` if a keyword with the same name is present at the same time in the same section (since we can figure out whether the user wanted to specify the section or the keyword by inspecting the value for the key: `dict` for a section)\n2. if a repeated keyword or section contains only one entry, the list can be omitted (in case of ambiguity priority is given to multiple values per keyword rather than keyword repetition)\n3. sections with default parameters can be formulated as dictionaries, as long as the default parameter values are unique and do not match section keyword or subsection names\n\nthe example from before in the simplified format:\n\n```json\n{\n  "global": {\n    "print_level": "medium",\n    "project_name": "test",\n    "run_type": "energy"\n  },\n  "force_eval": {\n    "method": "quickstep",\n    "DFT": {\n      "basis_set_file_name": "./BASIS_SETS",\n      "potential_file_name": "./POTENTIALS"\n    },\n    "xc": {\n      "xc_functional": {\n        "_": "PBE"\n      }\n    },\n    "subsys": {\n      "cell": {\n        "A": [ 4.07419, 0, 0 ],\n        "B": [ 2.037095, 3.52835204, 0 ],\n        "C": [ 2.037095, 1.17611735, 3.32656221 ],\n        "periodic": "XYZ"\n      },\n      "kind": {\n        "_": "Ge",\n        "element": "Ge",\n        "potential": "ALL-q32",\n        "basis_set": [ "ORB", "pob-TZVP" ]\n      },\n      "topology": {\n        "coord_file_name": "./struct.xyz",\n        "coord_file_format": "XYZ"\n      }\n    }\n  }\n}\n```\n\nor in YAML (with simplification rule #3 applied):\n\n```yaml\nglobal:\n  print_level: medium\n  project_name: test\n  run_type: energy\nforce_eval:\n  DFT:\n    basis_set_file_name: ./BASIS_SETS\n    potential_file_name: ./POTENTIALS\n  XC:\n    xc_functional:\n      _: PBE  # this can NOT be simplified since PBE could also be a subsection of xc_functional\n  method: quickstep\n  subsys:\n    cell:\n      A: [ 4.07419, 0.0, 0.0]\n      B: [ 2.037095, 3.52835204, 0.0]\n      C: [ 2.037095, 1.17611735, 3.32656221]\n      periodic: XYZ\n    kind:\n      Ge:\n        basis_set: [ORB, pob-TZVP]\n        element: Ge\n        potential: ALL-q32\n    topology:\n      coord_file_format: XYZ\n      coord_file_name: ./struct.xyz\n```\n',
    'author': 'Tiziano Müller',
    'author_email': 'tiziano.mueller@chem.uzh.ch',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/cp2k/cp2k-input-tools',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'entry_points': entry_points,
    'python_requires': '>=3.6.1,<4',
}


setup(**setup_kwargs)
