tiramisu/tiramisu/option/urloption.py

139 lines
4.7 KiB
Python
Raw Normal View History

2017-07-24 19:04:18 +02:00
# -*- coding: utf-8 -*-
2024-07-06 14:33:25 +02:00
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
2017-07-24 19:04:18 +02:00
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# The original `Config` design model is unproudly borrowed from
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
2023-05-11 15:44:48 +02:00
"""URLOption to check url value
"""
2017-07-24 19:04:18 +02:00
import re
from typing import Any, Optional, List, Dict
2017-07-24 19:04:18 +02:00
2023-05-11 15:44:48 +02:00
from ..setting import undefined
2017-07-24 19:04:18 +02:00
from ..i18n import _
2023-05-11 15:44:48 +02:00
from .option import Calculation
from .stroption import StrOption
2017-07-24 19:04:18 +02:00
from .domainnameoption import DomainnameOption
from .portoption import PortOption
2017-07-24 19:04:18 +02:00
class URLOption(StrOption):
2024-10-31 08:53:58 +01:00
"""URLOption to check url value"""
2017-07-24 19:04:18 +02:00
__slots__ = tuple()
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
2024-10-31 08:53:58 +01:00
_type = "URL"
2025-10-05 20:43:42 +02:00
_t_type = _("URL")
2017-07-24 19:04:18 +02:00
2024-10-31 08:53:58 +01:00
def __init__(
self,
name: str,
doc: str,
*args,
allow_ip: bool = False,
type: str = "domainname",
allow_without_dot=False,
allow_range: bool = False,
allow_zero: bool = False,
allow_wellknown: bool = True,
allow_registred: bool = True,
allow_private: bool = False,
**kwargs,
) -> None:
2023-05-11 15:44:48 +02:00
# pylint: disable=too-many-arguments,too-many-locals,redefined-builtin
2025-02-10 08:45:21 +01:00
extra = {}
extra["_domainname"] = DomainnameOption(
2025-05-12 08:53:39 +02:00
name,
doc,
allow_ip=allow_ip,
type=type,
allow_without_dot=allow_without_dot,
_extra=extra,
)
extra["_port"] = PortOption(
name,
doc,
allow_range=allow_range,
allow_zero=allow_zero,
allow_wellknown=allow_wellknown,
allow_registred=allow_registred,
allow_private=allow_private,
_extra=extra,
)
2024-10-31 08:53:58 +01:00
super().__init__(
name,
doc,
extra=extra,
*args,
**kwargs,
)
2024-10-31 08:53:58 +01:00
def _get_domain_port_files(self, value: str) -> (str, str):
if value.startswith("http://"):
type_ = "http"
value = value[7:]
2024-10-31 08:53:58 +01:00
elif value.startswith("https://"):
type_ = "https"
value = value[8:]
else:
2024-10-31 08:53:58 +01:00
raise ValueError(_("must start with http:// or " "https://"))
2017-07-24 19:04:18 +02:00
# get domain/files
2024-10-31 08:53:58 +01:00
splitted = value.split("/", 1)
2017-07-24 19:04:18 +02:00
if len(splitted) == 1:
domain = value
files = None
else:
domain, files = splitted
# if port in domain
2024-10-31 08:53:58 +01:00
splitted = domain.split(":", 1)
2017-07-24 19:04:18 +02:00
if len(splitted) == 1:
domain = splitted[0]
2024-10-31 08:53:58 +01:00
port = {"http": "80", "https": "443"}[type_]
2017-07-24 19:04:18 +02:00
else:
domain, port = splitted
return domain, port, files
2024-10-31 08:53:58 +01:00
def validate(self, value: str) -> None:
super().validate(value)
domain, port, files = self._get_domain_port_files(value)
# validate port
2024-10-31 08:53:58 +01:00
portoption = self.impl_get_extra("_port")
2025-02-07 07:46:53 +01:00
try:
portoption.validate(port)
except ValueError as err:
msg = _('the port "{0}" is invalid: {1}').format(domain, err)
raise ValueError(msg) from err
2017-07-24 19:04:18 +02:00
# validate domainname
2024-10-31 08:53:58 +01:00
domainnameoption = self.impl_get_extra("_domainname")
2025-02-07 07:46:53 +01:00
try:
domainnameoption.validate(domain)
except ValueError as err:
msg = _('the domain "{0}" is invalid: {1}').format(domain, err)
raise ValueError(msg) from err
# validate files
2024-10-31 08:53:58 +01:00
if files is not None and files != "" and not self.path_re.search(files):
raise ValueError(_("must ends with a valid resource name"))
2017-07-24 19:04:18 +02:00
def second_level_validation(self, value, warnings_only):
2023-05-11 15:44:48 +02:00
domain, port, _ = self._get_domain_port_files(value)
# validate port
2024-10-31 08:53:58 +01:00
portoption = self.impl_get_extra("_port")
portoption.second_level_validation(port, warnings_only)
# validate domainname
2024-10-31 08:53:58 +01:00
domainnameoption = self.impl_get_extra("_domainname")
domainnameoption.second_level_validation(domain, warnings_only)