diff --git a/.codacy.yml b/.codacy.yml
index 887131e0944..4e4c9b0a90f 100644
--- a/.codacy.yml
+++ b/.codacy.yml
@@ -3,10 +3,5 @@ exclude_paths:
- 'doc/joss-paper/**'
- 'etc/**'
- 'lib/cylc/tests/**'
- - 'lib/isodatetime/**'
- - 'lib/jinja2/**'
- - 'lib/markupsafe/**'
- - 'lib/parsec/tests/**'
- - 'licences/**'
- 'tests/**'
diff --git a/.travis/shellchecker b/.travis/shellchecker
index adda5378a16..d06191b842b 100755
--- a/.travis/shellchecker
+++ b/.travis/shellchecker
@@ -76,12 +76,12 @@ default () {
# run a strict check on all "functional" scripts
main '.' \
--exclude 'tests/' \
- --exclude 'lib/parsec/tests' \
+ --exclude 'lib/cylc/tests/parsec' \
--exclude 'etc/dev-bin/live-graph-movie.sh' \
-- -e SC1090
# run a lenient check on all test scripts
- main 'tests' 'lib/parsec/tests' -- -S error -e SC1090
+ main 'tests' 'lib/cylc/tests/parsec' -- -S error -e SC1090
}
if [[ $# -gt 0 ]]; then
diff --git a/bin/cylc-broadcast b/bin/cylc-broadcast
index f13e45b8289..31d3728434e 100755
--- a/bin/cylc-broadcast
+++ b/bin/cylc-broadcast
@@ -91,7 +91,7 @@ from cylc.network.client import SuiteRuntimeClient
from cylc.option_parsers import CylcOptionParser as COP
from cylc.print_tree import print_tree
from cylc.task_id import TaskID
-from parsec.config import ParsecConfig
+from cylc.parsec.config import ParsecConfig
REC_ITEM = re.compile(r'^\[([^\]]*)\](.*)$')
diff --git a/bin/cylc-edit b/bin/cylc-edit
index 67bf3fcffee..36de51a1c17 100755
--- a/bin/cylc-edit
+++ b/bin/cylc-edit
@@ -67,7 +67,7 @@ from subprocess import call
from shutil import copy
-from parsec.include import inline, \
+from cylc.parsec.include import inline, \
split_file, backup, backups, newfiles, cleanup, modtimes
diff --git a/bin/cylc-monitor b/bin/cylc-monitor
index 7428fffec46..61c5210bf3a 100755
--- a/bin/cylc-monitor
+++ b/bin/cylc-monitor
@@ -32,7 +32,7 @@ import os
import re
from time import sleep, time
-from parsec.OrderedDict import OrderedDict
+from cylc.parsec.OrderedDict import OrderedDict
from cylc.exceptions import ClientError
from cylc.option_parsers import CylcOptionParser as COP
diff --git a/bin/cylc-search b/bin/cylc-search
index a18c080c49e..3e85416044c 100755
--- a/bin/cylc-search
+++ b/bin/cylc-search
@@ -42,7 +42,7 @@ from collections import deque
from cylc.option_parsers import CylcOptionParser as COP
from cylc.suite_srv_files_mgr import SuiteSrvFilesManager
from cylc.terminal import cli_function
-from parsec.include import inline
+from cylc.parsec.include import inline
def section_level(heading):
diff --git a/bin/cylc-view b/bin/cylc-view
index a67485d2923..d07f0592aac 100755
--- a/bin/cylc-view
+++ b/bin/cylc-view
@@ -45,7 +45,7 @@ from cylc.option_parsers import CylcOptionParser as COP
from cylc.suite_srv_files_mgr import SuiteSrvFilesManager
from cylc.templatevars import load_template_vars
from cylc.terminal import cli_function
-from parsec.fileparse import read_and_proc
+from cylc.parsec.fileparse import read_and_proc
def parse_args():
diff --git a/lib/cylc/__init__.py b/lib/cylc/__init__.py
index 8738591660f..5df7176334e 100644
--- a/lib/cylc/__init__.py
+++ b/lib/cylc/__init__.py
@@ -19,7 +19,7 @@
import os
import sys
-from parsec import LOG
+from cylc.parsec import LOG
def environ_init():
diff --git a/lib/cylc/batch_sys_manager.py b/lib/cylc/batch_sys_manager.py
index 9e681a5bd65..ec898e9938d 100644
--- a/lib/cylc/batch_sys_manager.py
+++ b/lib/cylc/batch_sys_manager.py
@@ -124,7 +124,7 @@
JOB_LOG_STATUS)
from cylc.task_outputs import TASK_OUTPUT_SUCCEEDED
from cylc.wallclock import get_current_time_string
-from parsec.OrderedDict import OrderedDict
+from cylc.parsec.OrderedDict import OrderedDict
class JobPollContext(object):
diff --git a/lib/cylc/cfgspec/globalcfg.py b/lib/cylc/cfgspec/globalcfg.py
index 80a2ac580cc..37489120fe4 100644
--- a/lib/cylc/cfgspec/globalcfg.py
+++ b/lib/cylc/cfgspec/globalcfg.py
@@ -23,9 +23,9 @@
import shutil
from tempfile import mkdtemp
-from parsec.config import ParsecConfig
-from parsec.exceptions import ParsecError
-from parsec.upgrade import upgrader
+from cylc.parsec.config import ParsecConfig
+from cylc.parsec.exceptions import ParsecError
+from cylc.parsec.upgrade import upgrader
from cylc import LOG
from cylc.cfgvalidate import (
diff --git a/lib/cylc/cfgspec/suite.py b/lib/cylc/cfgspec/suite.py
index 7015b95a263..ea84951ed9e 100644
--- a/lib/cylc/cfgspec/suite.py
+++ b/lib/cylc/cfgspec/suite.py
@@ -19,8 +19,8 @@
from isodatetime.data import Calendar
-from parsec.upgrade import upgrader
-from parsec.config import ParsecConfig
+from cylc.parsec.upgrade import upgrader
+from cylc.parsec.config import ParsecConfig
from cylc.cfgvalidate import (
cylc_config_validate, CylcConfigValidator as VDR, DurationFloat)
diff --git a/lib/cylc/cfgvalidate.py b/lib/cylc/cfgvalidate.py
index c103f41689a..f60f383a561 100644
--- a/lib/cylc/cfgvalidate.py
+++ b/lib/cylc/cfgvalidate.py
@@ -25,7 +25,7 @@
from isodatetime.data import Calendar, Duration, TimePoint
from isodatetime.dumpers import TimePointDumper
from isodatetime.parsers import DurationParser, TimePointParser
-from parsec.validate import ParsecValidator, IllegalValueError
+from cylc.parsec.validate import ParsecValidator, IllegalValueError
from cylc.subprocctx import SubFuncContext
diff --git a/lib/cylc/config.py b/lib/cylc/config.py
index bce74a403ad..4a9ed35a9c4 100644
--- a/lib/cylc/config.py
+++ b/lib/cylc/config.py
@@ -37,8 +37,8 @@
from isodatetime.data import Calendar
from isodatetime.parsers import DurationParser
-from parsec.OrderedDict import OrderedDictWithDefaults
-from parsec.util import replicate
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.util import replicate
from cylc import LOG
from cylc.c3mro import C3
diff --git a/lib/cylc/cycling/iso8601.py b/lib/cylc/cycling/iso8601.py
index 5334603c4a9..6a03adfd636 100755
--- a/lib/cylc/cycling/iso8601.py
+++ b/lib/cylc/cycling/iso8601.py
@@ -32,7 +32,7 @@
SequenceDegenerateError, PointParsingError, IntervalParsingError
)
from cylc.wallclock import get_current_time_string
-from parsec.validate import IllegalValueError
+from cylc.parsec.validate import IllegalValueError
CYCLER_TYPE_ISO8601 = "iso8601"
CYCLER_TYPE_SORT_KEY_ISO8601 = "b"
diff --git a/lib/cylc/param_expand.py b/lib/cylc/param_expand.py
index 8f5cb1a3bcd..c846e5f2a85 100755
--- a/lib/cylc/param_expand.py
+++ b/lib/cylc/param_expand.py
@@ -62,7 +62,7 @@ def expand(template, params, results, values=None):
from cylc.exceptions import ParamExpandError
from cylc.task_id import TaskID
-from parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
# To split runtime heading name lists.
REC_NAMES = re.compile(r'(?:[^,<]|<[^>]*>)+')
diff --git a/lib/parsec/OrderedDict.py b/lib/cylc/parsec/OrderedDict.py
similarity index 100%
rename from lib/parsec/OrderedDict.py
rename to lib/cylc/parsec/OrderedDict.py
diff --git a/lib/parsec/README.md b/lib/cylc/parsec/README.md
similarity index 100%
rename from lib/parsec/README.md
rename to lib/cylc/parsec/README.md
diff --git a/lib/parsec/__init__.py b/lib/cylc/parsec/__init__.py
similarity index 100%
rename from lib/parsec/__init__.py
rename to lib/cylc/parsec/__init__.py
diff --git a/lib/parsec/config.py b/lib/cylc/parsec/config.py
similarity index 95%
rename from lib/parsec/config.py
rename to lib/cylc/parsec/config.py
index f89fe890611..8e17c8a9f14 100755
--- a/lib/parsec/config.py
+++ b/lib/cylc/parsec/config.py
@@ -17,13 +17,13 @@
# along with this program. If not, see .
import re
-from parsec.exceptions import (
+from cylc.parsec.exceptions import (
ParsecError, ItemNotFoundError, NotSingleItemError)
-from parsec.fileparse import parse
-from parsec.util import printcfg
-from parsec.validate import parsec_validate
-from parsec.OrderedDict import OrderedDictWithDefaults
-from parsec.util import itemstr, m_override, replicate, un_many
+from cylc.parsec.fileparse import parse
+from cylc.parsec.util import printcfg
+from cylc.parsec.validate import parsec_validate
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.util import itemstr, m_override, replicate, un_many
class ParsecConfig(object):
diff --git a/lib/parsec/empysupport.py b/lib/cylc/parsec/empysupport.py
similarity index 97%
rename from lib/parsec/empysupport.py
rename to lib/cylc/parsec/empysupport.py
index 221d7c45c7c..8988fb5a681 100644
--- a/lib/parsec/empysupport.py
+++ b/lib/cylc/parsec/empysupport.py
@@ -24,7 +24,7 @@
import em
import os
-from parsec.exceptions import EmPyError
+from cylc.parsec.exceptions import EmPyError
def empyprocess(flines, dir_, template_vars=None):
diff --git a/lib/parsec/example/cfgspec.py b/lib/cylc/parsec/example/cfgspec.py
similarity index 96%
rename from lib/parsec/example/cfgspec.py
rename to lib/cylc/parsec/example/cfgspec.py
index 18f445b501c..721ae850ba9 100644
--- a/lib/parsec/example/cfgspec.py
+++ b/lib/cylc/parsec/example/cfgspec.py
@@ -17,7 +17,7 @@
# along with this program. If not, see .
"""Legal items and validators for the parsec test config file."""
-from parsec.validate import ParsecValidator as vdr
+from cylc.parsec.validate import ParsecValidator as vdr
SPEC = {
diff --git a/lib/parsec/example/site.rc b/lib/cylc/parsec/example/site.rc
similarity index 100%
rename from lib/parsec/example/site.rc
rename to lib/cylc/parsec/example/site.rc
diff --git a/lib/parsec/example/test.py b/lib/cylc/parsec/example/test.py
similarity index 94%
rename from lib/parsec/example/test.py
rename to lib/cylc/parsec/example/test.py
index c2c0731c878..2e8a42e87d7 100755
--- a/lib/parsec/example/test.py
+++ b/lib/cylc/parsec/example/test.py
@@ -20,8 +20,8 @@
import os
import sys
-from cfgspec import SPEC
-from parsec.config import ParsecConfig
+from cylc.cfgspec.globalcfg import SPEC
+from cylc.parsec.config import ParsecConfig
import cylc.flags
# parse:
diff --git a/lib/parsec/example/user.rc b/lib/cylc/parsec/example/user.rc
similarity index 100%
rename from lib/parsec/example/user.rc
rename to lib/cylc/parsec/example/user.rc
diff --git a/lib/parsec/exceptions.py b/lib/cylc/parsec/exceptions.py
similarity index 99%
rename from lib/parsec/exceptions.py
rename to lib/cylc/parsec/exceptions.py
index 738f5ba67ce..1619649b30c 100644
--- a/lib/parsec/exceptions.py
+++ b/lib/cylc/parsec/exceptions.py
@@ -20,7 +20,7 @@
import os
import textwrap
-from parsec.util import itemstr
+from cylc.parsec.util import itemstr
TRACEBACK_WRAPPER = textwrap.TextWrapper()
diff --git a/lib/parsec/fileparse.py b/lib/cylc/parsec/fileparse.py
similarity index 96%
rename from lib/parsec/fileparse.py
rename to lib/cylc/parsec/fileparse.py
index f7ec8b1b7ea..247955fa71d 100644
--- a/lib/parsec/fileparse.py
+++ b/lib/cylc/parsec/fileparse.py
@@ -36,11 +36,11 @@
import sys
import re
-from parsec import LOG
-from parsec.exceptions import ParsecError, FileParseError
-from parsec.OrderedDict import OrderedDictWithDefaults
-from parsec.include import inline
-from parsec.util import itemstr
+from cylc.parsec import LOG
+from cylc.parsec.exceptions import ParsecError, FileParseError
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.include import inline
+from cylc.parsec.util import itemstr
# heading/sections can contain commas (namespace name lists) and any
@@ -246,7 +246,7 @@ def read_and_proc(fpath, template_vars=None, viewcfg=None, asedit=False):
if flines and re.match(r'^#![Ee]m[Pp]y\s*', flines[0]):
LOG.debug('Processing with EmPy')
try:
- from parsec.empysupport import empyprocess
+ from cylc.parsec.empysupport import empyprocess
except (ImportError, ModuleNotFoundError):
raise ParsecError('EmPy Python package must be installed '
'to process file: ' + fpath)
@@ -257,7 +257,7 @@ def read_and_proc(fpath, template_vars=None, viewcfg=None, asedit=False):
if flines and re.match(r'^#![jJ]inja2\s*', flines[0]):
LOG.debug('Processing with Jinja2')
try:
- from parsec.jinja2support import jinja2process
+ from cylc.parsec.jinja2support import jinja2process
except (ImportError, ModuleNotFoundError):
raise ParsecError('Jinja2 Python package must be installed '
'to process file: ' + fpath)
diff --git a/lib/parsec/include.py b/lib/cylc/parsec/include.py
similarity index 98%
rename from lib/parsec/include.py
rename to lib/cylc/parsec/include.py
index b5df15b5871..f562fd0f714 100644
--- a/lib/parsec/include.py
+++ b/lib/cylc/parsec/include.py
@@ -22,7 +22,7 @@
import sys
from shutil import copy as shcopy
-from parsec.exceptions import ParsecError, IncludeFileNotFoundError
+from cylc.parsec.exceptions import ParsecError, IncludeFileNotFoundError
done = []
diff --git a/lib/parsec/jinja2support.py b/lib/cylc/parsec/jinja2support.py
similarity index 99%
rename from lib/parsec/jinja2support.py
rename to lib/cylc/parsec/jinja2support.py
index e2336b71dbe..14d7089860d 100644
--- a/lib/parsec/jinja2support.py
+++ b/lib/cylc/parsec/jinja2support.py
@@ -35,8 +35,8 @@
TemplateNotFound,
TemplateSyntaxError)
-from parsec import LOG
-from parsec.exceptions import Jinja2Error
+from cylc.parsec import LOG
+from cylc.parsec.exceptions import Jinja2Error
TRACEBACK_LINENO = re.compile(r'(\s+)?File "", line (\d+)')
diff --git a/lib/parsec/upgrade.py b/lib/cylc/parsec/upgrade.py
similarity index 97%
rename from lib/parsec/upgrade.py
rename to lib/cylc/parsec/upgrade.py
index c70a7e7d9f5..2a3a00f8c4a 100755
--- a/lib/parsec/upgrade.py
+++ b/lib/cylc/parsec/upgrade.py
@@ -19,9 +19,9 @@
from logging import DEBUG, WARNING
-from parsec import LOG
-from parsec.exceptions import UpgradeError
-from parsec.OrderedDict import OrderedDict
+from cylc.parsec import LOG
+from cylc.parsec.exceptions import UpgradeError
+from cylc.parsec.OrderedDict import OrderedDict
class converter(object):
@@ -195,7 +195,7 @@ def upgrade(self):
if __name__ == "__main__":
import sys
- from parsec.util import printcfg
+ from cylc.parsec.util import printcfg
cfg = {
'item one': 1,
diff --git a/lib/parsec/util.py b/lib/cylc/parsec/util.py
similarity index 99%
rename from lib/parsec/util.py
rename to lib/cylc/parsec/util.py
index 7f20c9c1e09..3b5ada2b05b 100755
--- a/lib/parsec/util.py
+++ b/lib/cylc/parsec/util.py
@@ -25,7 +25,7 @@
from copy import copy
import sys
-from parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
def intlistjoin(lst):
diff --git a/lib/parsec/validate.py b/lib/cylc/parsec/validate.py
similarity index 99%
rename from lib/parsec/validate.py
rename to lib/cylc/parsec/validate.py
index 6d352493502..1796679fd97 100644
--- a/lib/parsec/validate.py
+++ b/lib/cylc/parsec/validate.py
@@ -27,7 +27,7 @@
import re
from textwrap import dedent
-from parsec.exceptions import (
+from cylc.parsec.exceptions import (
ListValueError, IllegalValueError, IllegalItemError)
@@ -227,7 +227,7 @@ def coerce_spaceless_str_list(cls, value, keys):
>>> ParsecValidator.coerce_spaceless_str_list(
... 'a, b c, d', ['foo']) # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
- parsec.exceptions.ListValueError: \
+ cylc.parsec.exceptions.ListValueError: \
(type=list) foo = a, b c, d - \
(list item "b c" cannot contain a space character)
@@ -250,7 +250,7 @@ def coerce_absolute_host_list(cls, value, keys):
... 'foo, bar, 127.0.0.1:8080, baz', ['pub']
... ) # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
- parsec.exceptions.ListValueError: \
+ cylc.parsec.exceptions.ListValueError: \
(type=list) pub = foo, bar, 127.0.0.1:8080, baz - \
(ambiguous host "127.0.0.1:8080")
diff --git a/lib/cylc/scheduler.py b/lib/cylc/scheduler.py
index f778d590ac5..5d48b2a3230 100644
--- a/lib/cylc/scheduler.py
+++ b/lib/cylc/scheduler.py
@@ -31,7 +31,7 @@
from uuid import uuid4
from isodatetime.parsers import TimePointParser
-from parsec.util import printcfg
+from cylc.parsec.util import printcfg
from cylc import LOG
from cylc.broadcast_mgr import BroadcastMgr
diff --git a/lib/cylc/task_events_mgr.py b/lib/cylc/task_events_mgr.py
index 238fe2c0288..d560dd26c54 100644
--- a/lib/cylc/task_events_mgr.py
+++ b/lib/cylc/task_events_mgr.py
@@ -34,7 +34,7 @@
import shlex
from time import time
-from parsec.config import ItemNotFoundError
+from cylc.parsec.config import ItemNotFoundError
from cylc import LOG
from cylc.cfgspec.glbl_cfg import glbl_cfg
diff --git a/lib/cylc/task_job_mgr.py b/lib/cylc/task_job_mgr.py
index 1f91e6e956e..535d29e838d 100644
--- a/lib/cylc/task_job_mgr.py
+++ b/lib/cylc/task_job_mgr.py
@@ -33,7 +33,7 @@
from time import time
import traceback
-from parsec.util import pdeepcopy, poverride
+from cylc.parsec.util import pdeepcopy, poverride
from cylc import LOG
from cylc.batch_sys_manager import JobPollContext
diff --git a/lib/cylc/task_pool.py b/lib/cylc/task_pool.py
index 6d5e0c635ca..98e8cbf4593 100644
--- a/lib/cylc/task_pool.py
+++ b/lib/cylc/task_pool.py
@@ -35,7 +35,7 @@
import json
from time import time
-from parsec.OrderedDict import OrderedDict
+from cylc.parsec.OrderedDict import OrderedDict
from cylc import LOG
from cylc.cycling.loader import get_point, standardise_point_string
diff --git a/lib/cylc/terminal.py b/lib/cylc/terminal.py
index 4d90e923bb9..5a778c87d46 100644
--- a/lib/cylc/terminal.py
+++ b/lib/cylc/terminal.py
@@ -2,7 +2,7 @@
import os
import sys
-from parsec.exceptions import ParsecError
+from cylc.parsec.exceptions import ParsecError
from cylc.cfgspec.glbl_cfg import glbl_cfg
from cylc.exceptions import CylcError
diff --git a/lib/cylc/tests/parsec/__init__.py b/lib/cylc/tests/parsec/__init__.py
new file mode 100644
index 00000000000..7872baaed1c
--- /dev/null
+++ b/lib/cylc/tests/parsec/__init__.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
diff --git a/lib/parsec/tests/getcfg/00-one-line.t b/lib/cylc/tests/parsec/getcfg/00-one-line.t
similarity index 100%
rename from lib/parsec/tests/getcfg/00-one-line.t
rename to lib/cylc/tests/parsec/getcfg/00-one-line.t
diff --git a/lib/parsec/tests/getcfg/00-one-line/test.rc b/lib/cylc/tests/parsec/getcfg/00-one-line/test.rc
similarity index 100%
rename from lib/parsec/tests/getcfg/00-one-line/test.rc
rename to lib/cylc/tests/parsec/getcfg/00-one-line/test.rc
diff --git a/lib/parsec/tests/nullcfg/01-empty-file/empty.rc b/lib/cylc/tests/parsec/getcfg/__init__.py
similarity index 100%
rename from lib/parsec/tests/nullcfg/01-empty-file/empty.rc
rename to lib/cylc/tests/parsec/getcfg/__init__.py
diff --git a/lib/cylc/tests/parsec/getcfg/bin/__init__.py b/lib/cylc/tests/parsec/getcfg/bin/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/parsec/tests/getcfg/bin/one-line.py b/lib/cylc/tests/parsec/getcfg/bin/one-line.py
similarity index 91%
rename from lib/parsec/tests/getcfg/bin/one-line.py
rename to lib/cylc/tests/parsec/getcfg/bin/one-line.py
index cc045c15c66..13d25abca85 100755
--- a/lib/parsec/tests/getcfg/bin/one-line.py
+++ b/lib/cylc/tests/parsec/getcfg/bin/one-line.py
@@ -25,8 +25,8 @@
sys.path.append(fpath + '/../../..')
-from parsec.config import ParsecConfig
-from parsec.validate import ParsecValidator as VDR
+from cylc.parsec.config import ParsecConfig
+from cylc.parsec.validate import ParsecValidator as VDR
SPEC = {'foo': {'bar': {'__MANY__': [VDR.V_STRING]}}}
cfg = ParsecConfig(SPEC)
diff --git a/lib/parsec/tests/getcfg/test_header b/lib/cylc/tests/parsec/getcfg/test_header
similarity index 100%
rename from lib/parsec/tests/getcfg/test_header
rename to lib/cylc/tests/parsec/getcfg/test_header
diff --git a/lib/parsec/tests/lib/bash/test_header b/lib/cylc/tests/parsec/lib/bash/test_header
similarity index 100%
rename from lib/parsec/tests/lib/bash/test_header
rename to lib/cylc/tests/parsec/lib/bash/test_header
diff --git a/lib/parsec/tests/nullcfg/01-empty-file.t b/lib/cylc/tests/parsec/nullcfg/01-empty-file.t
similarity index 100%
rename from lib/parsec/tests/nullcfg/01-empty-file.t
rename to lib/cylc/tests/parsec/nullcfg/01-empty-file.t
diff --git a/lib/cylc/tests/parsec/nullcfg/01-empty-file/empty.rc b/lib/cylc/tests/parsec/nullcfg/01-empty-file/empty.rc
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/cylc/tests/parsec/nullcfg/__init__.py b/lib/cylc/tests/parsec/nullcfg/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/cylc/tests/parsec/nullcfg/bin/__init__.py b/lib/cylc/tests/parsec/nullcfg/bin/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/parsec/tests/nullcfg/bin/empty.py b/lib/cylc/tests/parsec/nullcfg/bin/empty.py
similarity index 88%
rename from lib/parsec/tests/nullcfg/bin/empty.py
rename to lib/cylc/tests/parsec/nullcfg/bin/empty.py
index 9ad77587303..60847be60e0 100755
--- a/lib/parsec/tests/nullcfg/bin/empty.py
+++ b/lib/cylc/tests/parsec/nullcfg/bin/empty.py
@@ -23,9 +23,9 @@
import os
import sys
-from parsec.config import ParsecConfig
-from parsec.validate import ParsecValidator as VDR
-from parsec.OrderedDict import OrderedDict
+from cylc.parsec.config import ParsecConfig
+from cylc.parsec.validate import ParsecValidator as VDR
+from cylc.parsec.OrderedDict import OrderedDict
fpath = os.path.dirname(os.path.abspath(__file__))
# parsec
diff --git a/lib/parsec/tests/nullcfg/test_header b/lib/cylc/tests/parsec/nullcfg/test_header
similarity index 100%
rename from lib/parsec/tests/nullcfg/test_header
rename to lib/cylc/tests/parsec/nullcfg/test_header
diff --git a/lib/parsec/tests/synonyms/00-boolean.t b/lib/cylc/tests/parsec/synonyms/00-boolean.t
similarity index 100%
rename from lib/parsec/tests/synonyms/00-boolean.t
rename to lib/cylc/tests/parsec/synonyms/00-boolean.t
diff --git a/lib/parsec/tests/synonyms/00-boolean/boolean.rc b/lib/cylc/tests/parsec/synonyms/00-boolean/boolean.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/00-boolean/boolean.rc
rename to lib/cylc/tests/parsec/synonyms/00-boolean/boolean.rc
diff --git a/lib/parsec/tests/synonyms/01-integer.t b/lib/cylc/tests/parsec/synonyms/01-integer.t
similarity index 100%
rename from lib/parsec/tests/synonyms/01-integer.t
rename to lib/cylc/tests/parsec/synonyms/01-integer.t
diff --git a/lib/parsec/tests/synonyms/01-integer/integer.rc b/lib/cylc/tests/parsec/synonyms/01-integer/integer.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/01-integer/integer.rc
rename to lib/cylc/tests/parsec/synonyms/01-integer/integer.rc
diff --git a/lib/parsec/tests/synonyms/02-float.t b/lib/cylc/tests/parsec/synonyms/02-float.t
similarity index 100%
rename from lib/parsec/tests/synonyms/02-float.t
rename to lib/cylc/tests/parsec/synonyms/02-float.t
diff --git a/lib/parsec/tests/synonyms/02-float/float.rc b/lib/cylc/tests/parsec/synonyms/02-float/float.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/02-float/float.rc
rename to lib/cylc/tests/parsec/synonyms/02-float/float.rc
diff --git a/lib/parsec/tests/synonyms/03-string.t b/lib/cylc/tests/parsec/synonyms/03-string.t
similarity index 100%
rename from lib/parsec/tests/synonyms/03-string.t
rename to lib/cylc/tests/parsec/synonyms/03-string.t
diff --git a/lib/parsec/tests/synonyms/03-string/string.rc b/lib/cylc/tests/parsec/synonyms/03-string/string.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/03-string/string.rc
rename to lib/cylc/tests/parsec/synonyms/03-string/string.rc
diff --git a/lib/parsec/tests/synonyms/04-integer_list.t b/lib/cylc/tests/parsec/synonyms/04-integer_list.t
similarity index 100%
rename from lib/parsec/tests/synonyms/04-integer_list.t
rename to lib/cylc/tests/parsec/synonyms/04-integer_list.t
diff --git a/lib/parsec/tests/synonyms/04-integer_list/integer_list.rc b/lib/cylc/tests/parsec/synonyms/04-integer_list/integer_list.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/04-integer_list/integer_list.rc
rename to lib/cylc/tests/parsec/synonyms/04-integer_list/integer_list.rc
diff --git a/lib/parsec/tests/synonyms/05-float_list.t b/lib/cylc/tests/parsec/synonyms/05-float_list.t
similarity index 100%
rename from lib/parsec/tests/synonyms/05-float_list.t
rename to lib/cylc/tests/parsec/synonyms/05-float_list.t
diff --git a/lib/parsec/tests/synonyms/05-float_list/float_list.rc b/lib/cylc/tests/parsec/synonyms/05-float_list/float_list.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/05-float_list/float_list.rc
rename to lib/cylc/tests/parsec/synonyms/05-float_list/float_list.rc
diff --git a/lib/parsec/tests/synonyms/06-string_list.t b/lib/cylc/tests/parsec/synonyms/06-string_list.t
similarity index 100%
rename from lib/parsec/tests/synonyms/06-string_list.t
rename to lib/cylc/tests/parsec/synonyms/06-string_list.t
diff --git a/lib/parsec/tests/synonyms/06-string_list/string_list.rc b/lib/cylc/tests/parsec/synonyms/06-string_list/string_list.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/06-string_list/string_list.rc
rename to lib/cylc/tests/parsec/synonyms/06-string_list/string_list.rc
diff --git a/lib/parsec/tests/synonyms/07-string_list.t b/lib/cylc/tests/parsec/synonyms/07-string_list.t
similarity index 100%
rename from lib/parsec/tests/synonyms/07-string_list.t
rename to lib/cylc/tests/parsec/synonyms/07-string_list.t
diff --git a/lib/parsec/tests/synonyms/07-string_list/spaceless_string_list.rc b/lib/cylc/tests/parsec/synonyms/07-string_list/spaceless_string_list.rc
similarity index 100%
rename from lib/parsec/tests/synonyms/07-string_list/spaceless_string_list.rc
rename to lib/cylc/tests/parsec/synonyms/07-string_list/spaceless_string_list.rc
diff --git a/lib/cylc/tests/parsec/synonyms/__init__.py b/lib/cylc/tests/parsec/synonyms/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/cylc/tests/parsec/synonyms/bin/__init__.py b/lib/cylc/tests/parsec/synonyms/bin/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/parsec/tests/synonyms/bin/synonyms.py b/lib/cylc/tests/parsec/synonyms/bin/synonyms.py
similarity index 100%
rename from lib/parsec/tests/synonyms/bin/synonyms.py
rename to lib/cylc/tests/parsec/synonyms/bin/synonyms.py
diff --git a/lib/cylc/tests/parsec/synonyms/lib/__init__.py b/lib/cylc/tests/parsec/synonyms/lib/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/cylc/tests/parsec/synonyms/lib/python/__init__.py b/lib/cylc/tests/parsec/synonyms/lib/python/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/parsec/tests/synonyms/lib/python/cfgspec.py b/lib/cylc/tests/parsec/synonyms/lib/python/cfgspec.py
similarity index 95%
rename from lib/parsec/tests/synonyms/lib/python/cfgspec.py
rename to lib/cylc/tests/parsec/synonyms/lib/python/cfgspec.py
index 7c11d9a9edf..e96015a44a9 100644
--- a/lib/parsec/tests/synonyms/lib/python/cfgspec.py
+++ b/lib/cylc/tests/parsec/synonyms/lib/python/cfgspec.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from parsec.validate import ParsecValidator as VDR
+from cylc.parsec.validate import ParsecValidator as VDR
SPEC = {
'boolean': {'__MANY__': {'__MANY__': [VDR.V_BOOLEAN]}},
diff --git a/lib/parsec/tests/synonyms/test_header b/lib/cylc/tests/parsec/synonyms/test_header
similarity index 100%
rename from lib/parsec/tests/synonyms/test_header
rename to lib/cylc/tests/parsec/synonyms/test_header
diff --git a/lib/parsec/tests/test_config.py b/lib/cylc/tests/parsec/test_config.py
similarity index 91%
rename from lib/parsec/tests/test_config.py
rename to lib/cylc/tests/parsec/test_config.py
index 61e877a193b..b9512c71b1b 100644
--- a/lib/parsec/tests/test_config.py
+++ b/lib/cylc/tests/parsec/test_config.py
@@ -19,13 +19,12 @@
import tempfile
import unittest
-import parsec.config
-from parsec.exceptions import ParsecError
-import parsec.validate
+from cylc.parsec import config, validate
+from cylc.parsec.exceptions import ParsecError
from cylc.cfgvalidate import CylcConfigValidator as VDR
from cylc.cfgvalidate import cylc_config_validate
-from parsec.OrderedDict import OrderedDictWithDefaults
-from parsec.upgrade import upgrader
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.upgrade import upgrader
SAMPLE_SPEC_1 = {
'section1': {
@@ -72,14 +71,14 @@ def test_checkspec(self):
for spec, parents, exception in get_checkspec_params():
if exception:
with self.assertRaises(exception):
- parsec.config.ParsecConfig.checkspec(spec, parents)
+ config.ParsecConfig.checkspec(spec, parents)
else:
- parsec.config.ParsecConfig.checkspec(spec, parents)
+ config.ParsecConfig.checkspec(spec, parents)
def test_loadcfg(self):
with tempfile.NamedTemporaryFile() as output_file_name:
with tempfile.NamedTemporaryFile() as rcfile:
- parsec_config = parsec.config.ParsecConfig(
+ parsec_config = config.ParsecConfig(
spec=SAMPLE_SPEC_1,
upgrader=None, # new spec
output_fname=output_file_name.name,
@@ -121,7 +120,7 @@ def upg(cfg, description):
with tempfile.NamedTemporaryFile() as output_file_name:
with tempfile.NamedTemporaryFile() as rcfile:
- parsec_config = parsec.config.ParsecConfig(
+ parsec_config = config.ParsecConfig(
spec=SAMPLE_SPEC_1,
upgrader=upg,
output_fname=output_file_name.name,
@@ -166,7 +165,7 @@ def test_validate(self):
}
}
- parsec_config = parsec.config.ParsecConfig(
+ parsec_config = config.ParsecConfig(
spec=spec,
upgrader=None, # new spec
output_fname=None, # not going to call the loadcfg
@@ -177,7 +176,7 @@ def test_validate(self):
sparse = OrderedDictWithDefaults()
parsec_config.validate(sparse) # empty dict is OK
- with self.assertRaises(parsec.validate.IllegalItemError):
+ with self.assertRaises(validate.IllegalItemError):
sparse = OrderedDictWithDefaults()
sparse['name'] = 'True'
parsec_config.validate(sparse) # name is not valid
@@ -201,7 +200,7 @@ def test_expand(self):
with tempfile.NamedTemporaryFile() as output_file_name:
with tempfile.NamedTemporaryFile() as rcfile:
- parsec_config = parsec.config.ParsecConfig(
+ parsec_config = config.ParsecConfig(
spec=spec,
upgrader=None,
output_fname=output_file_name.name,
@@ -236,7 +235,7 @@ def test_get_item(self):
with tempfile.NamedTemporaryFile() as output_file_name:
with tempfile.NamedTemporaryFile() as rcfile:
- parsec_config = parsec.config.ParsecConfig(
+ parsec_config = config.ParsecConfig(
spec=spec,
upgrader=None,
output_fname=output_file_name.name,
@@ -264,15 +263,15 @@ def test_get_item(self):
cfg = parsec_config.get(keys=['section', 'name'], sparse=True)
self.assertEqual('test', cfg)
- with self.assertRaises(parsec.config.ItemNotFoundError):
+ with self.assertRaises(config.ItemNotFoundError):
parsec_config.get(keys=['section', 'a'], sparse=True)
def test_item_not_found_error(self):
- error = parsec.config.ItemNotFoundError("internal error")
+ error = config.ItemNotFoundError("internal error")
self.assertEqual('item not found: internal error', str(error))
def test_not_single_item_error(self):
- error = parsec.config.NotSingleItemError("internal error")
+ error = config.NotSingleItemError("internal error")
self.assertEqual('not a singular item: internal error', str(error))
diff --git a/lib/parsec/tests/test_empysupport.py b/lib/cylc/tests/parsec/test_empysupport.py
similarity index 91%
rename from lib/parsec/tests/test_empysupport.py
rename to lib/cylc/tests/parsec/test_empysupport.py
index 1c8f743d42b..95dc89b1737 100644
--- a/lib/parsec/tests/test_empysupport.py
+++ b/lib/cylc/tests/parsec/test_empysupport.py
@@ -24,13 +24,13 @@
import tempfile
import unittest
-from parsec.exceptions import EmPyError
-from parsec.fileparse import read_and_proc
+from cylc.parsec.exceptions import EmPyError
+from cylc.parsec.fileparse import read_and_proc
IS_EMPY_INSTALLED = True
try:
- import parsec.empysupport
+ from cylc.parsec import empysupport
except ImportError:
IS_EMPY_INSTALLED = False
@@ -43,7 +43,7 @@ def test_empysupport_empyprocess(self):
variables = {'name': 'Cylc'}
template_dir = tempfile.gettempdir()
- r = parsec.empysupport.empyprocess(lines, template_dir, variables)
+ r = empysupport.empyprocess(lines, template_dir, variables)
# after this, we would normally have an error in unittest as follows:
# AttributeError: ProxyFile instance has no attribute 'getvalue'
# That's due to a Proxy installed by EmPy to replace sys.stdout.
@@ -58,7 +58,7 @@ def test_empysupport_empyprocess(self):
lines = []
template_dir = tempfile.gettempdir()
- r = parsec.empysupport.empyprocess(lines, template_dir)
+ r = empysupport.empyprocess(lines, template_dir)
self.assertEqual(0, len(r))
diff --git a/lib/parsec/tests/test_fileparse.py b/lib/cylc/tests/parsec/test_fileparse.py
similarity index 99%
rename from lib/parsec/tests/test_fileparse.py
rename to lib/cylc/tests/parsec/test_fileparse.py
index 7ceeb1d26e7..ebfa6cdffb8 100644
--- a/lib/parsec/tests/test_fileparse.py
+++ b/lib/cylc/tests/parsec/test_fileparse.py
@@ -19,8 +19,8 @@
import tempfile
import unittest
-from parsec.exceptions import IncludeFileNotFoundError, Jinja2Error
-from parsec.fileparse import *
+from cylc.parsec.exceptions import IncludeFileNotFoundError, Jinja2Error
+from cylc.parsec.fileparse import *
def get_multiline():
diff --git a/lib/parsec/tests/test_include.py b/lib/cylc/tests/parsec/test_include.py
similarity index 99%
rename from lib/parsec/tests/test_include.py
rename to lib/cylc/tests/parsec/test_include.py
index 78ba585aa86..abb1a52e62f 100644
--- a/lib/parsec/tests/test_include.py
+++ b/lib/cylc/tests/parsec/test_include.py
@@ -24,7 +24,7 @@
import tempfile
import unittest
-from parsec.include import *
+from cylc.parsec.include import *
class TestInclude(unittest.TestCase):
diff --git a/lib/parsec/tests/test_jinja2support.py b/lib/cylc/tests/parsec/test_jinja2support.py
similarity index 99%
rename from lib/parsec/tests/test_jinja2support.py
rename to lib/cylc/tests/parsec/test_jinja2support.py
index 1873ef11b9f..2f590aa5d86 100644
--- a/lib/parsec/tests/test_jinja2support.py
+++ b/lib/cylc/tests/parsec/test_jinja2support.py
@@ -21,7 +21,7 @@
import jinja2
-from parsec.jinja2support import *
+from cylc.parsec.jinja2support import *
class TestJinja2support(unittest.TestCase):
diff --git a/lib/parsec/tests/test_ordered_dict.py b/lib/cylc/tests/parsec/test_ordered_dict.py
similarity index 98%
rename from lib/parsec/tests/test_ordered_dict.py
rename to lib/cylc/tests/parsec/test_ordered_dict.py
index c656b3c1b3a..5dc159725ba 100644
--- a/lib/parsec/tests/test_ordered_dict.py
+++ b/lib/cylc/tests/parsec/test_ordered_dict.py
@@ -18,7 +18,7 @@
import unittest
-from parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
class TestOrderedDict(unittest.TestCase):
diff --git a/lib/parsec/tests/test_parsec.py b/lib/cylc/tests/parsec/test_parsec.py
similarity index 96%
rename from lib/parsec/tests/test_parsec.py
rename to lib/cylc/tests/parsec/test_parsec.py
index 02eff80f389..c3784b43b2c 100644
--- a/lib/parsec/tests/test_parsec.py
+++ b/lib/cylc/tests/parsec/test_parsec.py
@@ -18,7 +18,7 @@
import unittest
-from parsec.exceptions import ParsecError
+from cylc.parsec.exceptions import ParsecError
class TestParsec(unittest.TestCase):
diff --git a/lib/parsec/tests/test_upgrade.py b/lib/cylc/tests/parsec/test_upgrade.py
similarity index 99%
rename from lib/parsec/tests/test_upgrade.py
rename to lib/cylc/tests/parsec/test_upgrade.py
index 07de7139148..bdadbec5282 100644
--- a/lib/parsec/tests/test_upgrade.py
+++ b/lib/cylc/tests/parsec/test_upgrade.py
@@ -18,7 +18,7 @@
import unittest
-from parsec.upgrade import *
+from cylc.parsec.upgrade import *
class TestUpgrade(unittest.TestCase):
diff --git a/lib/parsec/tests/test_util.py b/lib/cylc/tests/parsec/test_util.py
similarity index 99%
rename from lib/parsec/tests/test_util.py
rename to lib/cylc/tests/parsec/test_util.py
index ab528622c92..725fe2d7550 100644
--- a/lib/parsec/tests/test_util.py
+++ b/lib/cylc/tests/parsec/test_util.py
@@ -18,7 +18,7 @@
import unittest
-from parsec.util import *
+from cylc.parsec.util import *
class TestUtil(unittest.TestCase):
diff --git a/lib/parsec/tests/test_validate.py b/lib/cylc/tests/parsec/test_validate.py
similarity index 98%
rename from lib/parsec/tests/test_validate.py
rename to lib/cylc/tests/parsec/test_validate.py
index 63a4aab66b1..cb4a42bfa74 100644
--- a/lib/parsec/tests/test_validate.py
+++ b/lib/cylc/tests/parsec/test_validate.py
@@ -19,8 +19,8 @@
import unittest
from cylc.cfgvalidate import CylcConfigValidator as VDR
-from parsec.OrderedDict import OrderedDictWithDefaults
-from parsec.validate import *
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.validate import *
SAMPLE_SPEC_1 = {
'section1': {
@@ -106,7 +106,7 @@ def get_parsec_validator_invalid_values():
class TestValidate(unittest.TestCase):
- """Unit Tests for parsec.validate.ParsecValidator.coerce* methods."""
+ """Unit Tests for cylc.parsec.validate.ParsecValidator.coerce* methods."""
def test_list_value_error(self):
keys = ['a,', 'b', 'c']
@@ -204,7 +204,7 @@ def test_parsec_validator_invalid_key_with_many_invalid_values(self):
parsec_validator.validate(cfg, spec)
self.assertEqual(msg, str(cm.exception))
else:
- # parsec_validator.validate(cfg, spec)
+ # cylc.parsec_validator.validate(cfg, spec)
# let's use the alias `parsec_validate` here
parsec_validate(cfg, spec)
# TBD assertIsNotNone when 2.6+
diff --git a/pytest.ini b/pytest.ini
index 2afbca12971..c09d07ce97a 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -17,15 +17,14 @@
[pytest]
addopts = --verbose
--doctest-modules
- --ignore=lib/parsec/empysupport.py
- --ignore=lib/parsec/tests/getcfg/bin/one-line.py
- --ignore=lib/parsec/tests/synonyms/bin/synonyms.py
- --ignore=lib/parsec/tests/nullcfg/bin/empty.py
- --ignore=lib/parsec/example
+ --ignore=lib/cylc/parsec/empysupport.py
+ --ignore=lib/cylc/tests/parsec/getcfg/bin/one-line.py
+ --ignore=lib/cylc/tests/parsec/synonyms/bin/synonyms.py
+ --ignore=lib/cylc/tests/parsec/nullcfg/bin/empty.py
+ --ignore=lib/cylc/parsec/example
--ignore=lib/isodatetime
--ignore=lib/markupsafe
testpaths =
lib/cylc/
- lib/parsec/
lib/Jinja2Filters/
tests/lib/python/
diff --git a/tests/cylc-get-config/00-simple.t b/tests/cylc-get-config/00-simple.t
index c4f2798e2bb..c45d56cf82f 100755
--- a/tests/cylc-get-config/00-simple.t
+++ b/tests/cylc-get-config/00-simple.t
@@ -60,7 +60,7 @@ TEST_NAME=$TEST_NAME_BASE-python
run_ok $TEST_NAME cylc get-config --python --sparse $SUITE_NAME
run_ok $TEST_NAME-parse-config python3 -c "
import sys
-from parsec.OrderedDict import OrderedDictWithDefaults
+from cylc.parsec.OrderedDict import OrderedDictWithDefaults
with open(sys.argv[1], 'r') as file_:
print(eval(file_.read()))
" "$TEST_NAME.stdout"
diff --git a/tests/parsec b/tests/parsec
deleted file mode 120000
index 7d3dcc3c03a..00000000000
--- a/tests/parsec
+++ /dev/null
@@ -1 +0,0 @@
-../lib/parsec/tests
\ No newline at end of file
diff --git a/tests/parsec/getcfg/00-one-line.t b/tests/parsec/getcfg/00-one-line.t
new file mode 100755
index 00000000000..f0c171d6356
--- /dev/null
+++ b/tests/parsec/getcfg/00-one-line.t
@@ -0,0 +1,30 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test that one-line config print works
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=${TEST_NAME_BASE}
+one-line.py > foo.txt
+cmp_ok foo.txt << __END
+BAZ QUX
+__END
diff --git a/tests/parsec/getcfg/00-one-line/test.rc b/tests/parsec/getcfg/00-one-line/test.rc
new file mode 100644
index 00000000000..75419819e17
--- /dev/null
+++ b/tests/parsec/getcfg/00-one-line/test.rc
@@ -0,0 +1,5 @@
+
+[foo]
+ [[bar]]
+ baz = BAZ
+ qux = QUX
diff --git a/tests/parsec/getcfg/bin/one-line.py b/tests/parsec/getcfg/bin/one-line.py
new file mode 100755
index 00000000000..13d25abca85
--- /dev/null
+++ b/tests/parsec/getcfg/bin/one-line.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""Check that single-line config print works"""
+
+import os
+import sys
+
+fpath = os.path.dirname(os.path.abspath(__file__))
+# parsec
+sys.path.append(fpath + '/../../..')
+
+
+from cylc.parsec.config import ParsecConfig
+from cylc.parsec.validate import ParsecValidator as VDR
+
+SPEC = {'foo': {'bar': {'__MANY__': [VDR.V_STRING]}}}
+cfg = ParsecConfig(SPEC)
+cfg.loadcfg("test.rc")
+
+cfg.mdump(
+ [['foo', 'bar', 'baz'], ['foo', 'bar', 'qux']], oneline=True, sparse=True)
diff --git a/tests/parsec/getcfg/test_header b/tests/parsec/getcfg/test_header
new file mode 120000
index 00000000000..90bd5a36f92
--- /dev/null
+++ b/tests/parsec/getcfg/test_header
@@ -0,0 +1 @@
+../lib/bash/test_header
\ No newline at end of file
diff --git a/tests/parsec/lib/bash/test_header b/tests/parsec/lib/bash/test_header
new file mode 100644
index 00000000000..99e410fdc6e
--- /dev/null
+++ b/tests/parsec/lib/bash/test_header
@@ -0,0 +1,194 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# NAME
+# test_header
+#
+# SYNOPSIS
+# . $CYLC_DIR/t/lib/bash/test_header
+#
+# DESCRIPTION
+# Interface for constructing tests under a TAP harness (the "prove"
+# command).
+#
+# FUNCTIONS
+# set_test_number N
+# echo a total number of tests for TAP to read.
+# ok TEST_NAME
+# echo a TAP OK message for TEST_NAME.
+# fail TEST_NAME
+# echo a TAP fail message for TEST_NAME.
+# run_ok TEST_NAME COMMAND ...
+# Run COMMAND with any following options/arguments and store stdout
+# and stderr in TEST_NAME.stdout and TEST_NAME.stderr.
+# This is expected to have a return code of 0, which ok's the test.
+# run_fail TEST_NAME COMMAND ...
+# Run COMMAND with any following options/arguments and store stdout
+# and stderr in TEST_NAME.stdout and TEST_NAME.stderr.
+# This is expected to have a non-zero return code, which ok's the test.
+# cmp_ok FILE_TEST [FILE_CONTROL]
+# Compare FILE_TEST with a file or stdin given by FILE_CONTROL
+# (stdin if FILE_CONTROL is "-" or missing). If $TEST_DEBUG_CMP
+# is set, show differences using xxdiff.
+# grep_ok PATTERN FILE
+# Run "grep -q PATTERN FILE".
+# exists_ok FILE
+# Test that FILE exists
+# exists_fail FILE
+# Test that FILE does not exist
+# skip_tests N SKIP_REASON
+# echo "ok $((++T)) # skip SKIP_REASON" N times, where the number to skip.
+#-------------------------------------------------------------------------------
+set -eu
+
+FAILURES=0
+SIGNALS="EXIT INT"
+TEST_DIR=
+function FINALLY() {
+ for S in $SIGNALS; do
+ trap '' $S
+ done
+ if [[ -n $TEST_DIR ]]; then
+ cd ~
+ rm -rf $TEST_DIR
+ fi
+ if (($FAILURES > 0)); then
+ echo -e "\n stdout and stderr stored in: $TEST_LOG_DIR" >&2
+ fi
+}
+for S in $SIGNALS; do
+ trap "FINALLY $S" $S
+done
+
+TEST_NUMBER=0
+
+function set_test_number() {
+ echo "1..$1"
+}
+
+function ok() {
+ echo "ok $((++TEST_NUMBER)) - $*"
+}
+
+function fail() {
+ ((++FAILURES))
+ echo "not ok $((++TEST_NUMBER)) - $*"
+}
+
+function run_ok() {
+ local TEST_NAME=$1
+ shift 1
+ if ! "$@" 1>$TEST_NAME.stdout 2>$TEST_NAME.stderr; then
+ fail $TEST_NAME
+ mkdir -p $TEST_LOG_DIR
+ cp $TEST_NAME.stdout $TEST_LOG_DIR/$TEST_NAME.stdout
+ cp $TEST_NAME.stderr $TEST_LOG_DIR/$TEST_NAME.stderr
+ return
+ fi
+ ok $TEST_NAME
+}
+
+function run_fail() {
+ local TEST_NAME=$1
+ shift 1
+ if "$@" 1>$TEST_NAME.stdout 2>$TEST_NAME.stderr; then
+ fail $TEST_NAME
+ mkdir -p $TEST_LOG_DIR
+ cp $TEST_NAME.stdout $TEST_LOG_DIR/$TEST_NAME.stdout
+ cp $TEST_NAME.stderr $TEST_LOG_DIR/$TEST_NAME.stderr
+ return
+ fi
+ ok $TEST_NAME
+}
+
+function cmp_ok() {
+ local FILE_TEST=$1
+ local FILE_CONTROL=${2:--}
+ local TEST_NAME=$(basename $FILE_TEST)-cmp-ok
+ local CMP_COMMAND="cmp"
+ if [[ -n ${TEST_DEBUG_CMP:-} ]]; then
+ CMP_COMMAND="xxdiff -D"
+ fi
+ if $CMP_COMMAND $FILE_TEST $FILE_CONTROL; then
+ ok $TEST_NAME
+ return
+ fi
+ fail $TEST_NAME
+}
+
+function grep_ok() {
+ local BRE=$1
+ local FILE=$2
+ local TEST_NAME=$(basename $FILE)-grep-ok
+ if grep -q -e "$BRE" $FILE; then
+ ok $TEST_NAME
+ return
+ fi
+ fail $TEST_NAME
+}
+
+function exists_ok() {
+ local FILE=$1
+ local TEST_NAME=$(basename $FILE)-file-exists-ok
+ if [[ -a $FILE ]]; then
+ ok $TEST_NAME
+ return
+ fi
+ fail $TEST_NAME
+}
+
+function exists_fail() {
+ local FILE=$1
+ local TEST_NAME=$(basename $FILE)-file-exists-fail
+ if [[ ! -a $FILE ]]; then
+ ok $TEST_NAME
+ return
+ fi
+ fail $TEST_NAME
+}
+
+function skip() {
+ local N_TO_SKIP=$1
+ shift 1
+ local COUNT=0
+ while ((COUNT++ < N_TO_SKIP)); do
+ echo "ok $((++TEST_NUMBER)) # skip $*"
+ done
+}
+
+function install_test() {
+ ORIG_TEST_NAME=${2:-$TEST_NAME_BASE}
+ SNAME=$( echo ${TEST_SOURCE_DIR##*tests/} | tr '/' '_' )
+ NEW_TEST_NAME=$(date -u +%Y%m%d%H%M%S)_parse_test_${SNAME}_${1}
+ NTDIR=$TEST_DIR/$NEW_TEST_NAME/
+ mkdir $NTDIR
+ if [[ -d $TEST_SOURCE_DIR/$ORIG_TEST_NAME ]]; then
+ cp -r $TEST_SOURCE_DIR/$ORIG_TEST_NAME $NTDIR
+ else
+ mkdir $NTDIR/$ORIG_TEST_NAME
+ fi
+ cd $NTDIR/$ORIG_TEST_NAME
+}
+
+TEST_NAME_BASE=$(basename $0 .t)
+TEST_SOURCE_DIR=$(cd $(dirname $0) && pwd)
+PATH=$TEST_SOURCE_DIR/bin:$PATH
+TEST_DIR=$(mktemp -d)
+cd $TEST_DIR
+TEST_LOG_DIR=${TMPDIR:-/tmp}/parsec-tests/$(basename $TEST_SOURCE_DIR)
+
+set +e
diff --git a/tests/parsec/nullcfg/01-empty-file.t b/tests/parsec/nullcfg/01-empty-file.t
new file mode 100644
index 00000000000..b07df2e89fe
--- /dev/null
+++ b/tests/parsec/nullcfg/01-empty-file.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test that empty config files yield empty config dicts
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=${TEST_NAME_BASE}
+run_ok $TEST_NAME empty.py
diff --git a/tests/parsec/nullcfg/01-empty-file/empty.rc b/tests/parsec/nullcfg/01-empty-file/empty.rc
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/parsec/nullcfg/bin/empty.py b/tests/parsec/nullcfg/bin/empty.py
new file mode 100755
index 00000000000..60847be60e0
--- /dev/null
+++ b/tests/parsec/nullcfg/bin/empty.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+An empty config file should successfully yield an empty sparse config dict.
+"""
+
+
+import os
+import sys
+
+from cylc.parsec.config import ParsecConfig
+from cylc.parsec.validate import ParsecValidator as VDR
+from cylc.parsec.OrderedDict import OrderedDict
+
+fpath = os.path.dirname(os.path.abspath(__file__))
+# parsec
+sys.path.append(fpath + '/../../..')
+
+SPEC = {'meta': {'title': [VDR.V_STRING]}}
+cfg = ParsecConfig(SPEC)
+cfg.loadcfg("empty.rc")
+
+if cfg.get(sparse=True) != OrderedDict():
+ sys.exit(1)
diff --git a/tests/parsec/nullcfg/test_header b/tests/parsec/nullcfg/test_header
new file mode 120000
index 00000000000..90bd5a36f92
--- /dev/null
+++ b/tests/parsec/nullcfg/test_header
@@ -0,0 +1 @@
+../lib/bash/test_header
\ No newline at end of file
diff --git a/tests/parsec/synonyms/00-boolean.t b/tests/parsec/synonyms/00-boolean.t
new file mode 100644
index 00000000000..673f3cdc8c7
--- /dev/null
+++ b/tests/parsec/synonyms/00-boolean.t
@@ -0,0 +1,30 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of boolean items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 2
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=${TEST_NAME_BASE}-False
+run_ok $TEST_NAME synonyms.py boolean
+
+TEST_NAME=${TEST_NAME_BASE}-True
+run_ok $TEST_NAME synonyms.py boolean
diff --git a/tests/parsec/synonyms/00-boolean/boolean.rc b/tests/parsec/synonyms/00-boolean/boolean.rc
new file mode 100644
index 00000000000..00d1f2460cc
--- /dev/null
+++ b/tests/parsec/synonyms/00-boolean/boolean.rc
@@ -0,0 +1,49 @@
+# All legal ways of defining boolean values should parse to the same result.
+[boolean]
+ [[False]]
+ item 1 = False # comment
+ item 2 = 'False' # comment
+ item 3 = "False" # comment
+ item 4 = false # comment
+ item 5 = 'false' # comment
+ item 6 = "false" # comment
+ item 7 = '''False''' # comment
+ item 8 = '''false''' # comment
+ item 9 = '''
+ False
+ ''' # comment
+ item 10 = '''
+ false
+ ''' # comment
+ item 11 = """False""" # comment
+ item 12 = """false""" # comment
+ item 13 = """
+ False
+ """ # comment
+ item 14 = """
+ false
+ """ # comment
+
+ [[True]]
+ item 1 = True # comment
+ item 2 = 'True' # comment
+ item 3 = "True" # comment
+ item 4 = true # comment
+ item 5 = 'true' # comment
+ item 6 = "true" # comment
+ item 7 = '''True''' # comment
+ item 8 = '''true''' # comment
+ item 9 = '''
+ True
+ ''' # comment
+ item 10 = '''
+ true
+ ''' # comment
+ item 11 = """True""" # comment
+ item 12 = """true""" # comment
+ item 13 = """
+ True
+ """ # comment
+ item 14 = """
+ true
+ """ # comment
diff --git a/tests/parsec/synonyms/01-integer.t b/tests/parsec/synonyms/01-integer.t
new file mode 100644
index 00000000000..8a8e466227c
--- /dev/null
+++ b/tests/parsec/synonyms/01-integer.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of integer items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=$TEST_NAME_BASE
+run_ok $TEST_NAME synonyms.py integer
diff --git a/tests/parsec/synonyms/01-integer/integer.rc b/tests/parsec/synonyms/01-integer/integer.rc
new file mode 100644
index 00000000000..322da1a0f9f
--- /dev/null
+++ b/tests/parsec/synonyms/01-integer/integer.rc
@@ -0,0 +1,14 @@
+# All legals ways of defining integer values should parse to the same result.
+[integer]
+ [[99]]
+ item 1 = 99 # comment
+ item 2 = '99' # comment
+ item 3 = "99" # comment
+ item 4 = '''99''' # comment
+ item 5 = """99""" # comment
+ item 6 = '''
+ 99
+''' # comment
+ item 7 = """
+ 99
+""" # comment
diff --git a/tests/parsec/synonyms/02-float.t b/tests/parsec/synonyms/02-float.t
new file mode 100644
index 00000000000..e7a44cbe1e6
--- /dev/null
+++ b/tests/parsec/synonyms/02-float.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of float items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=$TEST_NAME_BASE
+run_ok $TEST_NAME synonyms.py float
diff --git a/tests/parsec/synonyms/02-float/float.rc b/tests/parsec/synonyms/02-float/float.rc
new file mode 100644
index 00000000000..222e2303f9f
--- /dev/null
+++ b/tests/parsec/synonyms/02-float/float.rc
@@ -0,0 +1,14 @@
+# All legals ways of defining float values should parse to the same result.
+[float]
+ [[9.9]]
+ item 1 = 9.9 # comment
+ item 2 = '9.9' # comment
+ item 3 = "9.9" # comment
+ item 4 = '''9.9''' # comment
+ item 5 = """9.9""" # comment
+ item 6 = '''
+ 9.9
+''' # comment
+ item 7 = """
+ 9.9
+""" # comment
diff --git a/tests/parsec/synonyms/03-string.t b/tests/parsec/synonyms/03-string.t
new file mode 100644
index 00000000000..7ab49b184c5
--- /dev/null
+++ b/tests/parsec/synonyms/03-string.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of string items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=$TEST_NAME_BASE
+run_ok $TEST_NAME synonyms.py string
diff --git a/tests/parsec/synonyms/03-string/string.rc b/tests/parsec/synonyms/03-string/string.rc
new file mode 100644
index 00000000000..e2524c9f834
--- /dev/null
+++ b/tests/parsec/synonyms/03-string/string.rc
@@ -0,0 +1,25 @@
+# All legals ways of defining string values should parse to the same result.
+[string]
+ [[the quick brown fox]]
+ item 1 = the quick brown fox # comment
+ item 2 = 'the quick brown fox' # comment
+ item 3 = "the quick brown fox" # comment
+ item 4 = '''the quick brown fox''' # comment
+ item 5 = """the quick brown fox""" # comment
+ item 6 = '''
+ the quick brown fox
+''' # comment
+ item 7 = """
+ the quick brown fox
+""" # comment
+ [[the quick #brown fox]]
+ item 1 = 'the quick #brown fox' # comment
+ item 2 = "the quick #brown fox" # comment
+ item 3 = '''the quick #brown fox''' # comment
+ item 4 = """the quick #brown fox""" # comment
+ item 5 = '''
+ the quick #brown fox
+''' # comment
+ item 6 = """
+ the quick #brown fox
+""" # comment
diff --git a/tests/parsec/synonyms/04-integer_list.t b/tests/parsec/synonyms/04-integer_list.t
new file mode 100644
index 00000000000..8e5aa59e682
--- /dev/null
+++ b/tests/parsec/synonyms/04-integer_list.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of integer list items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=$TEST_NAME_BASE
+run_ok $TEST_NAME synonyms.py integer_list
diff --git a/tests/parsec/synonyms/04-integer_list/integer_list.rc b/tests/parsec/synonyms/04-integer_list/integer_list.rc
new file mode 100644
index 00000000000..466efb937cf
--- /dev/null
+++ b/tests/parsec/synonyms/04-integer_list/integer_list.rc
@@ -0,0 +1,12 @@
+# All legals ways of defining integer lists should parse to the same result.
+[integer_list]
+ [[1_2_3_3_3_3_4_5_5_6]]
+ item 1 = 1,2,3,3,3,3,4,5,5,6 # comment
+ item 2 = 1, 2,3,3, 3 , 3, 4, 5 ,5,6 # comment
+ item 3 = 1,2,4*3,4,2*5,6 # comment
+ item 4 = "1","2","3","3","3", "3", "4","5", "5", "6" # comment
+ item 5 = "1","2","4*3","4","2*5","6" # comment
+ item 6 = '1','2','3','3','3', '3', '4','5', '5', '6' # comment
+ item 7 = '1','2','4*3','4','2*5','6' # comment
+ item 8 = 1, 2,3,\
+ 3, 3 , 3, 4, 5 ,5,6 # comment
diff --git a/tests/parsec/synonyms/05-float_list.t b/tests/parsec/synonyms/05-float_list.t
new file mode 100644
index 00000000000..b4e06933a7d
--- /dev/null
+++ b/tests/parsec/synonyms/05-float_list.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of float list items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=$TEST_NAME_BASE
+run_ok $TEST_NAME synonyms.py float_list
diff --git a/tests/parsec/synonyms/05-float_list/float_list.rc b/tests/parsec/synonyms/05-float_list/float_list.rc
new file mode 100644
index 00000000000..7f4faa477b8
--- /dev/null
+++ b/tests/parsec/synonyms/05-float_list/float_list.rc
@@ -0,0 +1,12 @@
+# All legals ways of defining float lists should parse to the same result.
+[float_list]
+ [[1.0_2.0_3.0_3.0_3.0_3.0_4.0_5.0_5.0_6.0]]
+ item 1 = 1.0,2.0,3.0,3.0,3.0,3.0,4.0,5.0,5.0,6.0 # comment
+ item 2 = 1.0, 2.0,3.0,3.0, 3.0 , 3.0, 4.0, 5.0 ,5.0,6.0 # comment
+ item 3 = 1.0,2.0,4*3.0,4.0,2*5.0,6.0 # comment
+ item 4 = "1.0","2.0","3.0","3.0","3.0", "3.0", "4.0","5.0", "5.0", "6.0" # comment
+ item 5 = "1.0","2.0","4*3.0","4.0","2*5.0","6.0" # comment
+ item 6 = '1.0','2.0','3.0','3.0','3.0', '3.0', '4.0','5.0', '5.0', '6.0' # comment
+ item 7 = '1.0','2.0','4*3.0','4.0','2*5.0','6.0' # comment
+ item 8 = 1.0, 2.0,3.0,\
+ 3.0, 3.0 , 3.0, 4.0, 5.0 ,5.0,6.0 # comment
diff --git a/tests/parsec/synonyms/06-string_list.t b/tests/parsec/synonyms/06-string_list.t
new file mode 100644
index 00000000000..ef255290dc6
--- /dev/null
+++ b/tests/parsec/synonyms/06-string_list.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of string list items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+TEST_NAME=$TEST_NAME_BASE
+run_ok $TEST_NAME synonyms.py string_list
diff --git a/tests/parsec/synonyms/06-string_list/string_list.rc b/tests/parsec/synonyms/06-string_list/string_list.rc
new file mode 100644
index 00000000000..3d8d21c4516
--- /dev/null
+++ b/tests/parsec/synonyms/06-string_list/string_list.rc
@@ -0,0 +1,29 @@
+# All legals ways of defining string lists should parse to the same result.
+# triple-quoted string values are currently illegal.
+[string_list]
+ [[the_quick_brown_fox]]
+ item 1 = the, quick, brown, fox # comment
+ item 2 = the, quick , brown, fox, # comment
+ item 3 = 'the', 'quick' , 'brown', 'fox', # comment
+ item 4 = "the", "quick" , "brown", "fox", # comment
+ item 5 = "the", "quick" , "brown",\
+ "fox", # comment
+ item 6 = the, quick, brown, fox # jumps, over # the lazy
+
+ [[the#c1_quick # c2_brown#c3_fox#c4]]
+ # internal comments should be preserved
+ item 1 = 'the#c1', 'quick # c2' , 'brown#c3', 'fox#c4', # comment
+ item 2 = "the#c1", "quick # c2" , "brown#c3", "fox#c4", # comment
+ item 3 = "the#c1", "quick # c2" , "brown#c3",\
+ "fox#c4", # comment
+
+ [[theCOMMAc1_quick COMMA c2_brownCOMMAc3_foxCOMMAc4]]
+ # internal commas should be preserved
+ item 1 = 'the,c1', 'quick , c2' , 'brown,c3', 'fox,c4', # comment
+ item 2 = "the,c1", "quick , c2" , "brown,c3", "fox,c4", # comment
+ item 3 = "the,c1", "quick , c2" , "brown,c3",\
+ "fox,c4", # comment
+
+ [[NULL]]
+ item 1 =
+ item 2 = # comment
diff --git a/tests/parsec/synonyms/07-string_list.t b/tests/parsec/synonyms/07-string_list.t
new file mode 100644
index 00000000000..c86d177105b
--- /dev/null
+++ b/tests/parsec/synonyms/07-string_list.t
@@ -0,0 +1,27 @@
+#!/bin/bash
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#-------------------------------------------------------------------------------
+# Test parsing of string list items
+. $(dirname $0)/test_header
+
+#-------------------------------------------------------------------------------
+set_test_number 1
+
+install_test $TEST_NAME_BASE
+#-------------------------------------------------------------------------------
+#synonyms.py spaceless_string_list >&2
+run_ok "${TEST_NAME_BASE}-good" synonyms.py spaceless_string_list
diff --git a/tests/parsec/synonyms/07-string_list/spaceless_string_list.rc b/tests/parsec/synonyms/07-string_list/spaceless_string_list.rc
new file mode 100644
index 00000000000..60bdfaeeaf4
--- /dev/null
+++ b/tests/parsec/synonyms/07-string_list/spaceless_string_list.rc
@@ -0,0 +1,29 @@
+# All legals ways of defining string lists should parse to the same result.
+# triple-quoted string values are currently illegal.
+[spaceless_string_list]
+ [[the_quick_brown_fox]]
+ item 1 = the, quick, brown, fox # comment
+ item 2 = the, quick , brown, fox, # comment
+ item 3 = 'the', 'quick' , 'brown', 'fox', # comment
+ item 4 = "the", "quick" , "brown", "fox", # comment
+ item 5 = "the", "quick" , "brown",\
+ "fox", # comment
+ item 6 = the, quick, brown, fox # jumps, over # the lazy
+
+ [[the#c1_quick#c2_brown#c3_fox#c4]]
+ # internal comments should be preserved
+ item 1 = 'the#c1', 'quick#c2' , 'brown#c3', 'fox#c4', # comment
+ item 2 = "the#c1", "quick#c2" , "brown#c3", "fox#c4", # comment
+ item 3 = "the#c1", "quick#c2" , "brown#c3",\
+ "fox#c4", # comment
+
+ [[theCOMMAc1_quickCOMMAc2_brownCOMMAc3_foxCOMMAc4]]
+ # internal commas should be preserved
+ item 1 = 'the,c1', 'quick,c2' , 'brown,c3', 'fox,c4', # comment
+ item 2 = "the,c1", "quick,c2" , "brown,c3", "fox,c4", # comment
+ item 3 = "the,c1", "quick,c2" , "brown,c3",\
+ "fox,c4", # comment
+
+ [[NULL]]
+ item 1 =
+ item 2 = # comment
diff --git a/tests/parsec/synonyms/bin/synonyms.py b/tests/parsec/synonyms/bin/synonyms.py
new file mode 100755
index 00000000000..a7c2887976c
--- /dev/null
+++ b/tests/parsec/synonyms/bin/synonyms.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+import sys
+
+fpath = os.path.dirname(os.path.abspath(__file__))
+
+# spec
+sys.path.append(fpath + '/../lib/python')
+# parsec
+sys.path.append(fpath + '/../../..')
+
+# NOTE: ignore this warning, as this is defined in this test lib/python folder
+from cfgspec import SPEC
+from cylc.parsec.config import ParsecConfig
+
+rcname = sys.argv[1]
+rcfile = rcname + '.rc'
+
+cfg = ParsecConfig(SPEC)
+
+cfg.loadcfg(rcfile)
+
+res = cfg.get(sparse=True)
+
+for expected in res[rcname]:
+
+ vals = list(cfg.get([rcname, expected], sparse=True).values())
+ expected = expected.replace('COMMA', ',').replace('NULL', '')
+
+ if rcname == 'boolean':
+ expected = (expected == 'True') or False
+
+ elif rcname == 'integer':
+ expected = int(expected)
+
+ elif rcname == 'float':
+ expected = float(expected)
+
+ elif rcname == 'integer_list':
+ expected = [int(i) for i in expected.split('_')]
+
+ elif rcname == 'float_list':
+ expected = [float(i) for i in expected.split('_')]
+
+ elif rcname in ['string_list', 'spaceless_string_list']:
+ if expected:
+ expected = expected.split('_')
+ else:
+ expected = []
+
+ if vals.count(expected) != len(vals):
+ print(vals, ' is not all ', expected, file=sys.stderr)
+ sys.exit("FAIL")
+ else:
+ print("OK")
diff --git a/tests/parsec/synonyms/lib/python/cfgspec.py b/tests/parsec/synonyms/lib/python/cfgspec.py
new file mode 100644
index 00000000000..e96015a44a9
--- /dev/null
+++ b/tests/parsec/synonyms/lib/python/cfgspec.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
+# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+from cylc.parsec.validate import ParsecValidator as VDR
+
+SPEC = {
+ 'boolean': {'__MANY__': {'__MANY__': [VDR.V_BOOLEAN]}},
+ 'integer': {'__MANY__': {'__MANY__': [VDR.V_INTEGER]}},
+ 'float': {'__MANY__': {'__MANY__': [VDR.V_FLOAT]}},
+ 'string': {'__MANY__': {'__MANY__': [VDR.V_STRING]}},
+ 'string_list': {'__MANY__': {'__MANY__': [VDR.V_STRING_LIST]}},
+ 'spaceless_string_list': {'__MANY__': {'__MANY__': [
+ VDR.V_SPACELESS_STRING_LIST]}},
+ 'float_list': {'__MANY__': {'__MANY__': [VDR.V_FLOAT_LIST]}},
+ 'integer_list': {'__MANY__': {'__MANY__': [VDR.V_INTEGER_LIST]}},
+}
diff --git a/tests/parsec/synonyms/test_header b/tests/parsec/synonyms/test_header
new file mode 120000
index 00000000000..90bd5a36f92
--- /dev/null
+++ b/tests/parsec/synonyms/test_header
@@ -0,0 +1 @@
+../lib/bash/test_header
\ No newline at end of file