22import shutil
33import sys
44import textwrap
5+ from collections .abc import Callable
56from collections .abc import Sequence
67from datetime import datetime
78from functools import partial
9+ from typing import Any
10+ from typing import Optional
811from uuid import UUID
912
1013import ulid
@@ -47,45 +50,40 @@ def make_parser(prog: str | None = None) -> argparse.ArgumentParser:
4750 )
4851 b .add_argument (
4952 "--from-int" ,
50- type = int ,
5153 metavar = "<int>" ,
5254 help = "create from integer" ,
5355 )
5456 b .add_argument (
5557 "--from-hex" ,
56- type = str ,
5758 metavar = "<str>" ,
5859 help = "create from 32 character hex value" ,
5960 )
6061 b .add_argument (
6162 "--from-str" ,
62- type = str ,
6363 metavar = "<str>" ,
6464 help = "create from base32 encoded string of length 26" ,
6565 )
6666 b .add_argument (
6767 "--from-timestamp" ,
68- type = parse_numeric ,
6968 metavar = "<int|float>" ,
7069 help = "create from timestamp either as float in secs or int as millis" ,
7170 )
7271 b .add_argument (
7372 "--from-datetime" ,
74- type = datetime .fromisoformat ,
7573 metavar = "<iso8601>" ,
7674 help = "create from datetime. The timestamp part of the ULID will be taken from the datetime" ,
7775 )
7876 b .add_argument (
7977 "--from-uuid" ,
80- type = UUID ,
8178 metavar = "<uuid>" ,
8279 help = "create from given UUID. The timestamp part will be random." ,
8380 )
8481 b .set_defaults (func = build )
8582
8683 s = subparsers .add_parser ("show" , help = "show properties of a ULID" )
8784 s .add_argument ("ulid" , help = "the ULID to inspect. The special value - reads from stdin" )
88- s .add_argument ("--uuid" , action = "store_true" , help = "convert to UUID" )
85+ s .add_argument ("--uuid" , action = "store_true" , help = "convert to fully random UUID" )
86+ s .add_argument ("--uuid4" , action = "store_true" , help = "convert to RFC 4122 compliant UUIDv4" )
8987 s .add_argument ("--hex" , action = "store_true" , help = "convert to hex" )
9088 s .add_argument ("--int" , action = "store_true" , help = "convert to int" )
9189 s .add_argument ("--timestamp" , "--ts" , action = "store_true" , help = "show timestamp" )
@@ -94,42 +92,50 @@ def make_parser(prog: str | None = None) -> argparse.ArgumentParser:
9492 return parser
9593
9694
95+ def main (argv : Sequence [str ], prog : str | None = None ) -> None :
96+ args = make_parser (prog ).parse_args (argv )
97+ args .func (args )
98+
99+
100+ def from_value_or_stdin (value : str , convert : Optional [Callable [[str ], Any ]] = None ) -> Any :
101+ value = sys .stdin .readline ().strip () if value == "-" else value
102+ if convert is not None :
103+ return convert (value )
104+ return value
105+
106+
97107def parse_numeric (s : str ) -> int | float :
98108 try :
99109 return int (s )
100110 except ValueError :
101111 return float (s )
102112
103113
104- def main (argv : Sequence [str ], prog : str | None = None ) -> None :
105- args = make_parser (prog ).parse_args (argv )
106- args .func (args )
107-
108-
109114def build (args : argparse .Namespace ) -> None :
110115 ulid : ULID
111116 if args .from_int is not None :
112- ulid = ULID .from_int (args .from_int )
117+ ulid = ULID .from_int (from_value_or_stdin ( args .from_int , int ) )
113118 elif args .from_hex is not None :
114- ulid = ULID .from_hex (args .from_hex )
119+ ulid = ULID .from_hex (from_value_or_stdin ( args .from_hex ) )
115120 elif args .from_str is not None :
116- ulid = ULID .from_str (args .from_str )
121+ ulid = ULID .from_str (from_value_or_stdin ( args .from_str ) )
117122 elif args .from_timestamp is not None :
118- ulid = ULID .from_timestamp (args .from_timestamp )
123+ ulid = ULID .from_timestamp (from_value_or_stdin ( args .from_timestamp , parse_numeric ) )
119124 elif args .from_datetime is not None :
120- ulid = ULID .from_datetime (args .from_datetime )
125+ ulid = ULID .from_datetime (from_value_or_stdin ( args .from_datetime , datetime . fromisoformat ) )
121126 elif args .from_uuid is not None :
122- ulid = ULID .from_uuid (args .from_uuid )
127+ ulid = ULID .from_uuid (from_value_or_stdin ( args .from_uuid , UUID ) )
123128 else :
124129 ulid = ULID ()
125130 print (ulid )
126131
127132
128133def show (args : argparse .Namespace ) -> None :
129- value = sys .stdin .readline ().strip () if args .ulid == "-" else args .ulid
130- ulid : ULID = ULID .from_str (value )
134+ ulid : ULID = ULID .from_str (from_value_or_stdin (args .ulid ))
131135 if args .uuid :
132136 print (ulid .to_uuid ())
137+ elif args .uuid4 :
138+ print (ulid .to_uuid4 ())
133139 elif args .hex :
134140 print (ulid .hex )
135141 elif args .int :
0 commit comments