Supported Types
This document outlines all of the types that arc supports for parameters.
When possible, arc uses builtin and standard library data types. But if no type is available, or the builtin types don't provide the neccessary functionality, arc may implement a custom type.
Builtin Types¶
str
¶
str(v)
is used which, in most cases, will be comparable to no change.
This is considered the default type is no type is specified.
int
¶
arc uses int(v)
to convert the value. Note that decimal input (1.4
) will result in an error, not a narrowing operation.
float
¶
Likewise, arc uses float(v)
. Ingeter values will be converted to a float (2 -> 2.0
)
bool
¶
Used to denote a Flag
import arc
@arc.command
def hello(firstname: str, reverse: bool):
if reverse:
firstname = firstname[::-1]
arc.print(f"Hello, {firstname}! Hope you have a wonderful day!")
hello()
$ python parameter_flag.py Joseph
Hello, Joseph! Hope you have a wonderful day!
$ python parameter_flag.py Joseph --reverse
Hello, hpesoJ! Hope you have a wonderful day!
bytes
¶
Converted using v.encode()
dict
¶
Allows a list of comma-seperated key-value pairs. Can be typed generically on both keys and values.
import arc
@arc.command
def command(numbers: dict[str, int]):
arc.print(numbers)
command()
Collection Types¶
arc allows you to collect multiple values from the command line into a single argument for your comamnd. To do this, you use the collection types: list
, set
and tuple
list
¶
import arc
@arc.command
def main(names: list):
for name in names:
arc.print(name)
main()
list
can accept any number of values, you won't be able to add additional arguments after names
. Any other positional arguments would have to come before names
.
set
¶
Similar to list
, but will filter out any non-unique elements.
import arc
@arc.command
def main(vals: set):
arc.print("Unique values:")
arc.print("\n".join(vals))
main()
tuple
¶
Similar to list
, but with some additional functionality.
According to PEP 484:
tuple
represents an arbitrarily sized tuple of any type. In arc, this will behave the same aslist
tuple[int, ...]
represents an arbitrarily sized tuple of integers. In arc, this will behave the same aslist[int]
tuple[int, int]
represents a size-two tuple of integers. In arc, this behavior is unique totuple
as the parameter will only select 2 values from input.
Sub Typing¶
Collections can be sub-typed so that each item will be converted to the proper type:
import arc
@arc.command
def main(nums: list[int]):
arc.print("The total is: ", sum(nums))
main()
Collections as Options¶
When used as an option, it allows the option to be used multiple times:
import arc
@arc.command
def main(*, names: list):
for name in names:
arc.print(name)
main()
Collection Lengths¶
You can specify how many items should be provided to a collection type with a type validator, specifically Len()
from typing import Annotated
import arc
from arc.types.middleware import Len
@arc.command()
def command(vals: Annotated[list[int], Len(2, 10)]):
arc.print(vals)
command()
$ python length.py 1 2 3 4 5 6
[1, 2, 3, 4, 5, 6]
$ python length.py 1
USAGE
length.py [-h] vals [vals...]
invalid value for vals: expects between 2 and 10 arguments
Standard Library Types¶
typing.Any
¶
Equivelant to str
typing.TypedDict
¶
Constrains a dictionary input to a specific subset of keys and specific value types.
typing.Union
¶
Allows the input to be multiple different types.
from typing import Union
import arc
@arc.command
def main(number: Union[int, str]):
arc.print(type(number))
main()
arc will attempt to coerce the input into each type, from left to right. The first to succeed will be passed along to the command.
Warning
You cannot have a type like typing.Union[list, int]
as collection types need to be known at definition of a command rather
than during data validation.
Python 3.10's union syntax is also valid: int | str
pathlib.Path
¶
Path won't perform any validation checks to assert that the input is a valid path, but it just offers the convenience of working with path objects rather than strings. Check the ValidPath
custom type for additional validations
ipaddress.IPv4Address
¶
Uses ipaddress.IPv4Address(v)
for conversion, so anything valid there is valid here.
ipaddress.IPv6Address
¶
Same as above
re.Pattern
¶
Compile a regular expression using re.compile()
datetime.datetime
¶
Convert string input to a datetime object
Type Arguments¶
You can provide the expected format of the datetime string via a type argument:
from typing import Annotated
import arc
from arc import types
import datetime
@arc.command
def command(date: Annotated[datetime.datetime, types.DateTimeArgs("%Y-%m-%d")]):
arc.print(date)
command()
datetime.date
¶
Convert string input to a date object.
types.DateArgs
is equivalent to the above example.
datetime.time
¶
Convert string input to a time object
types.TimeArgs
is equivalent to the above example.
Constrained Input¶
typing.Literal
¶
Enforces that the input must be a specific sub-set of values
from typing import Literal
import arc
@arc.command
def main(word: Literal["foo", "bar", 1]):
arc.print(word, type(word))
main()
$ python literal_argument.py foo
foo <class 'str'>
$ python literal_argument.py 1
1 <class 'int'>
$ python literal_argument.py other
USAGE
literal_argument.py [-h] word
invalid value for word: must be foo, bar or 1
Note
arc compares the input to the string-ified version of each value in the Literal. So for the second example above, the comparison that succedded was "1" == "1"
not 1 == 1
.
enum.Enum
¶
Similar to typing.Literal
, restricts the input to a specific sub-set of values
from enum import Enum
import arc
arc.configure(autocomplete=True)
class Color(Enum):
RED = "red"
YELLOW = "yellow"
GREEN = "green"
# Could also use:
# Color = Literal["red", "yellow", "green"]
@arc.command
def paint(color: Color):
if color is Color.RED:
arc.print("You painted the walls the bloodiest of reds")
elif color is Color.YELLOW:
arc.print("You painted the walls the most fabulous yellow")
else:
arc.print("You painted the walls the deepest of greens")
paint()
$ python paint.py red
You painted the walls the bloodiest of reds
$ python paint.py blue
USAGE
paint.py [-h] [--autocomplete AUTOCOMPLETE] color
invalid value for color: must be red, yellow or green
arc Types¶
arc provides a variety of additional types exported from the arc.types
module:
Warning
arc types are sort of weird in the general Python sense. While it will become
more aparent later as to why this is the case, know that you cannot usually
create the types on your own and have the expected behavior. If you do need / want
to do this, you can use: arc.convert(<value>, <type>)
Context
¶
Annotating an argument with this gives you access to the current execution context.
State
¶
Reference State for details
Prompt
¶
Gives you access to a Prompt instance
SemVer
¶
A type to support semantically-versioned strings based on the spec found here
User
(*NIX ONLY)¶
A representation of a *nix user. The input should be the name of the *nix user.
Group
(*NIX ONLY)¶
A representation of a *nix group. The input should be the name of the *nix group.
File System Types¶
File
¶
One of the most common things that a CLI tool is likely to do, is take in a file name as input, and interact with that file in some way. arc's advanced typing system makes this trivial, with the details around ensuring the file exists, opening it, and closing it handled by arc for you.
arc provides this functionality through its arc.types.File
type. Let's use it to read out the first line of the source code's README.
import arc
from arc.types import File
@arc.command
def command(file: File.Read):
arc.print(file.readline())
command()
There are constants defined on File
(like File.Read
above) for all common actions (Read
, Write
, Append
, ReadWrite
, etc...). You can view them all in the reference
ValidPath
¶
pathlib.Path
but asserts that the provided path actually exists
FilePath
¶
pathlib.Path
but asserts that the path both exists and is a file
DirectoryPath
¶
pathlib.Path
but asserts that the path both exists and is a directory
Networking Types¶
IpAddress
¶
Union type for IPv4Address
and IPv6Address
Url
¶
Parses the strings input using urllib.parse.urlparse
HttpUrl
¶
Url
that asserts the scheme to be http
or https
WebSocketUrl
¶
Url
that asserts the scheme to be wss
FtpUrl
¶
Url
that asserts the scheme to be ftp
MysqlUrl
¶
Url
that asserts the scheme to be `mysql
PostgresUrl
¶
Url
that checks that it is a valid PostgreSQL URL
Number Types¶
Note
For any types that simply change the base of the input (like Binary
or Hex
), it is essentially equivelant to int(v, base=<base>)
.
Binary
¶
Accepts integers as binary stings (0101010110
).
Oct
¶
Accepts integers in base 8
Hex
¶
Accepts integers in base 16
PositveInt
¶
Enforces that the integer must be greater than 0
NegativeInt
¶
Enforces that the integer must be less than 0
PositveFloat
¶
Enforces that the float must be greater than 0
NegativeFloat
¶
Enforces that the float must be less than 0
AnyNumber
¶
Accepts floats, and integers in any base.
String Types¶
Char
¶
Enforces that the string can only be a single character long
Password
¶
When prompted for input, the user's input will not be echoed to the screen.
Email
¶
Enforces that the string is a valid email address