2929
3030
3131def is_ip (val : celtypes .Value , ver : typing .Optional [celtypes .Value ] = None ) -> celpy .Result :
32- """Validate whether a given string is a valid IP address according to an optional IP version.
32+ """Return True if the string is an IPv4 or IPv6 address, optionally limited to a specific version.
33+
34+ Version 0 or None means either 4 or 6. Passing a version other than 0, 4, or 6 always returns False.
3335
3436 IPv4 addresses are expected in the dotted decimal format, for example "192.168.5.21".
3537 IPv6 addresses are expected in their text representation, for example "::1" or "2001:0DB8:ABCD:0012::0".
3638
3739 Both formats are well-defined in the internet standard RFC 3986. Zone
3840 identifiers for IPv6 addresses (for example "fe80::a%en1") are supported.
3941
40- Args:
41- val (celTypes.Value): The string to validate.
42- version (typing.Optional[celtypes.Value]): An optional version to use for validating the IP address.
43- Passing None for a version of 0 means either 4 or 6.
44- Passing a version other than 0, 4, or 6 always returns False.
45-
46- Returns:
47- True if the string is an IPv4 or IPv6 address, optionally limited to a specific version.
48-
49- Raises:
50- celpy.CELEvalError: If val is not an instance of celtypes.StringType or
51- if version is not an instance of celtypes.IntType and is not None.
5242 """
53-
5443 if not isinstance (val , celtypes .StringType ):
5544 msg = "invalid argument, expected string"
5645 raise celpy .CELEvalError (msg )
@@ -80,6 +69,25 @@ def _is_ip(string: str, version: int) -> bool:
8069
8170
8271def is_ip_prefix (val : celtypes .Value , * args ) -> celpy .Result :
72+ """Return True if the string is a valid IP with prefix length, optionally
73+ limited to a specific version (v4 or v6), and optionally requiring the host
74+ portion to be all zeros.
75+
76+ An address prefix divides an IP address into a network portion, and a host portion.
77+ The prefix length specifies how many bits the network portion has.
78+ For example, the IPv6 prefix "2001:db8:abcd:0012::0/64" designates the
79+ left-most 64 bits as the network prefix. The range of the network is 2**64
80+ addresses, from 2001:db8:abcd:0012::0 to 2001:db8:abcd:0012:ffff:ffff:ffff:ffff.
81+
82+ An address prefix may include a specific host address, for example
83+ "2001:db8:abcd:0012::1f/64". With strict = true, this is not permitted. The
84+ host portion must be all zeros, as in "2001:db8:abcd:0012::0/64".
85+
86+ The same principle applies to IPv4 addresses. "192.168.1.0/24" designates
87+ the first 24 bits of the 32-bit IPv4 as the network prefix.
88+
89+ """
90+
8391 if not isinstance (val , celtypes .StringType ):
8492 msg = "invalid argument, expected string or bytes"
8593 raise celpy .CELEvalError (msg )
@@ -118,7 +126,7 @@ def _is_ip_prefix(string: str, version: int, *, strict=False) -> bool:
118126
119127
120128def is_email (string : celtypes .Value ) -> celpy .Result :
121- """Return true if the string is an email address, for example "foo@example.com".
129+ """Return True if the string is an email address, for example "foo@example.com".
122130
123131 Conforms to the definition for a valid email address from the HTML standard.
124132 Note that this standard willfully deviates from RFC 5322, which allows many
@@ -134,7 +142,7 @@ def is_email(string: celtypes.Value) -> celpy.Result:
134142
135143
136144def is_uri (string : celtypes .Value ) -> celpy .Result :
137- """Return true if the string is a URI, for example "https://example.com/foo/bar?baz=quux#frag".
145+ """Return True if the string is a URI, for example "https://example.com/foo/bar?baz=quux#frag".
138146
139147 URI is defined in the internet standard RFC 3986.
140148 Zone Identifiers in IPv6 address literals are supported (RFC 6874).
@@ -148,7 +156,7 @@ def is_uri(string: celtypes.Value) -> celpy.Result:
148156
149157
150158def is_uri_ref (string : celtypes .Value ) -> celpy .Result :
151- """Return true if the string is a URI Reference - a URI such as "https://example.com/foo/bar?baz=quux#frag" or
159+ """Return True if the string is a URI Reference - a URI such as "https://example.com/foo/bar?baz=quux#frag" or
152160 a Relative Reference such as "./foo/bar?query".
153161
154162 URI, URI Reference, and Relative Reference are defined in the internet standard RFC 3986.
@@ -163,13 +171,25 @@ def is_uri_ref(string: celtypes.Value) -> celpy.Result:
163171
164172
165173def is_hostname (val : celtypes .Value ) -> celpy .Result :
174+ """Returns True if the string is a valid hostname, for example "foo.example.com".
175+
176+ A valid hostname follows the rules below:
177+ - The name consists of one or more labels, separated by a dot (".").
178+ - Each label can be 1 to 63 alphanumeric characters.
179+ - A label can contain hyphens ("-"), but must not start or end with a hyphen.
180+ - The right-most label must not be digits only.
181+ - The name can have a trailing dot, for example "foo.example.com.".
182+ - The name can be 253 characters at most, excluding the optional trailing dot.
183+
184+ """
166185 if not isinstance (val , celtypes .StringType ):
167186 msg = "invalid argument, expected string"
168187 raise celpy .CELEvalError (msg )
169188 return celtypes .BoolType (_is_hostname (val ))
170189
171190
172191def _is_hostname (val : str ) -> bool :
192+ """Internal implementation"""
173193 if len (val ) > 253 :
174194 return False
175195
@@ -219,6 +239,18 @@ def _is_port(val: str) -> bool:
219239
220240
221241def is_host_and_port (string : celtypes .Value , port_required : celtypes .Value ) -> celpy .Result :
242+ """Return True if the string is a valid host/port pair, for example "example.com:8080".
243+
244+ If the argument `port_required` is True, the port is required. If the argument
245+ is False, the port is optional.
246+
247+ The host can be one of:
248+ - An IPv4 address in dotted decimal format, for example "192.168.0.1".
249+ - An IPv6 address enclosed in square brackets, for example "[::1]".
250+ - A hostname, for example "example.com".
251+
252+ The port is separated by a colon. It must be non-empty, with a decimal number in the range of 0-65535, inclusive.
253+ """
222254 if not isinstance (string , celtypes .StringType ):
223255 msg = "invalid argument, expected string"
224256 raise celpy .CELEvalError (msg )
@@ -287,18 +319,15 @@ def unique(val: celtypes.Value) -> celpy.Result:
287319
288320
289321class Ipv4 :
290- """a class"""
322+ """Ipv4 is a class used to parse a given string to determine if it is a valid IPv4 address or address prefix. """
291323
292324 _string : str
293325 _index : int
294326 _octets : bytearray
295327 _prefix_len : int
296328
297329 def __init__ (self , string : str ):
298- """ipv4
299-
300- Args:
301- """
330+ """Initialize an Ipv4 validation class with a given string."""
302331
303332 super ().__init__ ()
304333 self ._string = string
@@ -317,23 +346,21 @@ def address_prefix(self) -> bool:
317346 )
318347
319348 def get_bits (self ) -> int :
320- """Get the bits of an address parsed through address() or address_prefix()
349+ """Return the 32-bit value of an address parsed through address() or address_prefix().
350+
351+ Return -1 if no address was parsed successfully.
321352
322- Returns:
323- The 32-bit value if address was parsed successfully. 0 if not successful.
324353 """
325354 if len (self ._octets ) != 4 :
326- return 0
355+ return - 1
327356
328357 return (self ._octets [0 ] << 24 ) | (self ._octets [1 ] << 16 ) | (self ._octets [2 ] << 8 ) | self ._octets [3 ]
329358
330359 def is_prefix_only (self ) -> bool :
331- """Determines TODO
360+ """Return True if all bits to the right of the prefix-length are all zeros.
332361
333- Behavior is undefined if address_prefix() has not been called before or has returned false .
362+ Behavior is undefined if address_prefix() has not been called before, or has returned False .
334363
335- Returns:
336- True if all bits to the right of the prefix-length are all zeros. False otherwise.
337364 """
338365 bits = self .get_bits ()
339366
@@ -348,6 +375,8 @@ def is_prefix_only(self) -> bool:
348375 return bits == masked
349376
350377 def __prefix_length (self ) -> bool :
378+ """Store value in `prefix_len`"""
379+
351380 start = self ._index
352381
353382 while True :
@@ -436,11 +465,12 @@ def __dec_octet(self) -> bool:
436465 return False
437466
438467 def __digit (self ) -> bool :
439- """Reports whether the current position is a digit.
468+ """Report whether the current position is a digit.
440469
441470 Method parses the rule:
442471
443- DIGIT = %x30-39 ; 0-9
472+ DIGIT = %x30-39 ; 0-9
473+
444474 """
445475
446476 if self ._index >= len (self ._string ):
@@ -458,11 +488,7 @@ def __take(self, char: str) -> bool:
458488
459489 If char is at the current index, increment the index.
460490
461- Returns:
462- True if char is at the current index. False if char is not at the
463- current index or the end of string has been reached.
464491 """
465-
466492 if self ._index >= len (self ._string ):
467493 return False
468494
@@ -474,34 +500,20 @@ def __take(self, char: str) -> bool:
474500
475501
476502class Ipv6 :
477- """a class"""
503+ """Ipv6 is a class used to parse a given string to determine if it is a valid IPv6 address or address prefix. """
478504
479505 _string : str
480506 _index : int
481- _pieces : list [int ]
482- _double_colon_at : int
507+ _pieces : list [int ] # 16-bit pieces found
508+ _double_colon_at : int # Number of 16-bit pieces found when double colon was found.
483509 _double_colon_seen : bool
484- _dotted_raw : str
485- _dotted_addr : typing .Optional [Ipv4 ]
510+ _dotted_raw : str # Dotted notation for right-most 32 bits.
511+ _dotted_addr : typing .Optional [Ipv4 ] # Dotted notation successfully parsed as Ipv4.
486512 _zone_id_found : bool
487- _prefix_len : int
513+ _prefix_len : int # 0 -128
488514
489515 def __init__ (self , string : str ):
490- """ipv6
491-
492- Args:
493-
494- Attributes:
495- _string (str): The string to parse.
496- _index (int): The index.
497- _pieces (list[int]): 16-bit pieces found.
498- _double_colon_at (bool): Number of 16-bit pieces found when double colon was found.
499- _double_colon_seen (bool): Whether a double colon has been seen in string.
500- _dotted_raw (str): Dotted notation for right-most 32 bits.
501- _dotted_addr (typing.Optional[Ipv4]): Dotted notation successfully parsed as Ipv4.
502- _zone_id_found (bool): Whether a zone ID has been found in string.
503- _prefix_len (int): 0 - 128
504- """
516+ """Initialize a URI validation class with a given string."""
505517
506518 super ().__init__ ()
507519 self ._string = string
@@ -514,12 +526,11 @@ def __init__(self, string: str):
514526 self ._zone_id_found = False
515527
516528 def get_bits (self ) -> int :
517- """Get the bits of an address parsed through address() or address_prefix() as a 128-bit integer .
529+ """Return the 128-bit value of an address parsed through address() or address_prefix().
518530
519- Returns:
520- The 128-bit value if address was parsed successfully. 0 if no address was parsed successfully.
521- """
531+ Return 0 if no address was parsed successfully.
522532
533+ """
523534 p16 = self ._pieces
524535
525536 # Handle dotted decimal, add to p16
@@ -555,12 +566,10 @@ def get_bits(self) -> int:
555566 )
556567
557568 def is_prefix_only (self ) -> bool :
558- """Determine whether string is an ipv6 prefix only .
569+ """Return True if all bits to the right of the prefix-length are all zeros .
559570
560- Behavior is undefined if address_prefix() has not been called before.
571+ Behavior is undefined if address_prefix() has not been called before, or has returned False .
561572
562- Returns:
563- True if all bits to the right of the prefix-length are all zeros. False otherwise.
564573 """
565574 bits = self .get_bits ()
566575 mask : int
@@ -594,6 +603,7 @@ def address_prefix(self) -> bool:
594603 )
595604
596605 def __prefix_length (self ) -> bool :
606+ """Store value in `prefix_len`."""
597607 start = self ._index
598608
599609 while True :
@@ -629,7 +639,7 @@ def __prefix_length(self) -> bool:
629639 return False
630640
631641 def __address_part (self ) -> bool :
632- """Store the dotted notation for right-most 32 bits in dottedRaw / dottedAddr if found."""
642+ """Store dotted notation for right-most 32 bits in dotted_raw / dotted_addr if found."""
633643
634644 while True :
635645 if self ._index >= len (self ._string ):
@@ -671,14 +681,12 @@ def __address_part(self) -> bool:
671681 def __zone_id (self ) -> bool :
672682 """Determine whether string contains a zoneID.
673683
674- Method parses the rule from RFC 6874:
684+ There is no definition for the character set allowed in the zone
685+ identifier. RFC 4007 permits basically any non-null string.
675686
676- ZoneID = 1*( unreserved / pct-encoded )
687+ RFC 6874: ZoneID = 1*( unreserved / pct-encoded )
677688
678- There is no definition for the character set allowed in the zone identifier.
679- RFC 4007 permits basically any non-null string.
680689 """
681-
682690 start = self ._index
683691
684692 if self .__take ("%" ):
@@ -699,7 +707,7 @@ def __dotted(self) -> bool:
699707
700708 Method parses the rule:
701709
702- 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
710+ 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
703711
704712 Stores match in _dotted_raw.
705713 """
@@ -726,7 +734,7 @@ def __h16(self) -> bool:
726734
727735 Method parses the rule:
728736
729- h16 = 1*4HEXDIG
737+ h16 = 1*4HEXDIG
730738
731739 Stores 16-bit value in _pieces.
732740 """
@@ -765,9 +773,9 @@ def __hex_dig(self) -> bool:
765773
766774 Method parses the rule:
767775
768- HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
769- """
776+ HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
770777
778+ """
771779 if self ._index >= len (self ._string ):
772780 return False
773781
@@ -785,9 +793,9 @@ def __digit(self) -> bool:
785793
786794 Method parses the rule:
787795
788- DIGIT = %x30-39 ; 0-9
789- """
796+ DIGIT = %x30-39 ; 0-9
790797
798+ """
791799 if self ._index >= len (self ._string ):
792800 return False
793801
@@ -803,11 +811,7 @@ def __take(self, char: str) -> bool:
803811
804812 If char is at the current index, increment the index.
805813
806- Returns:
807- True if char is at the current index. False if char is not at the
808- current index or the end of string has been reached.
809814 """
810-
811815 if self ._index >= len (self ._string ):
812816 return False
813817
@@ -1441,7 +1445,7 @@ def __pct_encoded(self) -> bool:
14411445
14421446 pct-encoded = "%" HEXDIG HEXDIG
14431447
1444- Sets `_pct_encoded_found` to true if a valid triplet was found
1448+ Sets `_pct_encoded_found` to True if a valid triplet was found
14451449
14461450 """
14471451 start = self ._index
@@ -1554,6 +1558,7 @@ def __take(self, char: str) -> bool:
15541558 """Take the given char at the current index.
15551559
15561560 If char is at the current index, increment the index.
1561+
15571562 """
15581563 if self ._index >= len (self ._string ):
15591564 return False
0 commit comments