###########################################################################
# Copyright (c), The AiiDA team. All rights reserved. #
# This file is part of the AiiDA code. #
# #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################
"""Module for various text-based string validation.
"""
import re
from click.types import StringParamType
__all__ = ('EmailType', 'EntryPointType', 'HostnameType', 'NonEmptyStringParamType', 'LabelStringType')
[docs]
class NonEmptyStringParamType(StringParamType):
"""Parameter whose values have to be string and non-empty."""
name = 'nonemptystring'
[docs]
def convert(self, value, param, ctx):
newval = super().convert(value, param, ctx)
# Note: Valid :py:class:`click.ParamType`s need to pass through None unchanged
if newval is None:
return None
if not newval: # empty string
self.fail('Empty string is not valid!')
return newval
[docs]
def __repr__(self):
return 'NONEMPTYSTRING'
[docs]
class LabelStringType(NonEmptyStringParamType):
"""Parameter accepting valid label strings.
Non-empty string, made up of word characters (includes underscores [1]), dashes, and dots.
[1] See https://docs.python.org/3/library/re.html
"""
name = 'labelstring'
ALPHABET = r'\w\.\-'
[docs]
def convert(self, value, param, ctx):
newval = super().convert(value, param, ctx)
if not re.match(f'^[{self.ALPHABET}]*$', newval):
self.fail('Please use only alphanumeric characters, dashes, underscores or dots')
return newval
[docs]
def __repr__(self):
return 'LABELSTRING'
HOSTNAME_REGEX = re.compile(
r'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])'
r'(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$'
)
[docs]
class HostnameType(StringParamType):
"""Parameter corresponding to a valid hostname (or empty) string.
Regex according to https://stackoverflow.com/a/3824105/1069467
"""
name = 'hostname'
[docs]
def convert(self, value, param, ctx):
newval = super().convert(value, param, ctx)
if newval and not HOSTNAME_REGEX.match(newval):
self.fail('Please enter a valid hostname.')
return newval
[docs]
def __repr__(self):
return 'HOSTNAME'
[docs]
class EmailType(StringParamType):
"""Parameter whose values have to correspond to a valid email address format.
.. note:: For the moment, we do not require the domain suffix, i.e. 'aiida@localhost' is still valid.
"""
name = 'email'
[docs]
def convert(self, value, param, ctx):
newval = super().convert(value, param, ctx)
if not re.match(r'[^@]+@[^@]+(\.[^@]+){0,1}', newval):
self.fail('Please enter a valid email.')
return newval
[docs]
def __repr__(self):
return 'EMAIL'
[docs]
class EntryPointType(NonEmptyStringParamType):
"""Parameter whose values have to be valid Python entry point strings.
See https://packaging.python.org/en/latest/specifications/entry-points/
"""
name = 'entrypoint'
[docs]
def convert(self, value, param, ctx):
newval = super().convert(value, param, ctx)
if not re.match(r'[\w.-]', newval):
self.fail(
'Please enter a valid entry point string: Use only letters, numbers, undercores, dots and dashes.'
)
return newval
[docs]
def __repr__(self):
return 'ENTRYPOINT'