rm TaintedString for string; some proc -> func (#53)

* rm TaintedString for string; some proc -> func

* procs which interact with macros in certain ways can't be funcs in Nim 1.2
This commit is contained in:
tersec 2022-06-03 18:24:59 +00:00 committed by GitHub
parent d06f6187dc
commit fc03a0c4e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 93 deletions

View File

@ -338,7 +338,7 @@ Furthermore, you can extend the behavior of the library by providing
overloads such as:
```nim
proc parseCmdArg*(T: type Foo, p: TaintedString): T =
proc parseCmdArg*(T: type Foo, p: string): T =
## This provides parsing and validation for fields having the `Foo` type.
## You should raise `ConfigurationError` in case of detected problems.
...

View File

@ -60,7 +60,7 @@ const
confutils_description_width {.intdefine.} = 80
confutils_narrow_terminal_width {.intdefine.} = 36
proc getFieldName(caseField: NimNode): NimNode =
func getFieldName(caseField: NimNode): NimNode =
result = caseField
if result.kind == nnkIdentDefs: result = result[0]
if result.kind == nnkPragmaExpr: result = result[0]
@ -390,7 +390,7 @@ func getNextArgIdx(cmd: CmdInfo, consumedArgIdx: int): int =
if cmd.opts[i].kind == Arg and cmd.opts[i].idx > consumedArgIdx:
return cmd.opts[i].idx
return -1
-1
proc noMoreArgsError(cmd: CmdInfo): string =
result = if cmd.isSubCommand: "The command '$1'" % [cmd.name]
@ -399,23 +399,23 @@ proc noMoreArgsError(cmd: CmdInfo): string =
if cmd.hasArgs: result.add " additional"
result.add " arguments"
proc findOpt(opts: openArray[OptInfo], name: string): OptInfo =
func findOpt(opts: openArray[OptInfo], name: string): OptInfo =
for opt in opts:
if cmpIgnoreStyle(opt.name, name) == 0 or
cmpIgnoreStyle(opt.abbr, name) == 0:
return opt
proc findOpt(activeCmds: openArray[CmdInfo], name: string): OptInfo =
func findOpt(activeCmds: openArray[CmdInfo], name: string): OptInfo =
for i in countdown(activeCmds.len - 1, 0):
let found = findOpt(activeCmds[i].opts, name)
if found != nil: return found
proc findCmd(cmds: openArray[CmdInfo], name: string): CmdInfo =
func findCmd(cmds: openArray[CmdInfo], name: string): CmdInfo =
for cmd in cmds:
if cmpIgnoreStyle(cmd.name, name) == 0:
return cmd
proc findSubCmd(cmd: CmdInfo, name: string): CmdInfo =
func findSubCmd(cmd: CmdInfo, name: string): CmdInfo =
let subCmdDiscriminator = cmd.getSubCmdDiscriminator
if subCmdDiscriminator != nil:
let cmd = findCmd(subCmdDiscriminator.subCmds, name)
@ -423,7 +423,7 @@ proc findSubCmd(cmd: CmdInfo, name: string): CmdInfo =
return nil
proc startsWithIgnoreStyle(s: string, prefix: string): bool =
func startsWithIgnoreStyle(s: string, prefix: string): bool =
# Similar in spirit to cmpIgnoreStyle, but compare only the prefix.
var i = 0
var j = 0
@ -461,13 +461,13 @@ else:
template printCmdTree(cmd: CmdInfo) = discard
# TODO remove the overloads here to get better "missing overload" error message
proc parseCmdArg*(T: type InputDir, p: TaintedString): T =
proc parseCmdArg*(T: type InputDir, p: string): T =
if not dirExists(p.string):
raise newException(ValueError, "Directory doesn't exist")
result = T(p)
T(p)
proc parseCmdArg*(T: type InputFile, p: TaintedString): T =
proc parseCmdArg*(T: type InputFile, p: string): T =
# TODO this is needed only because InputFile cannot be made
# an alias of TypedInputFile at the moment, because of a generics
# caching issue
@ -481,10 +481,10 @@ proc parseCmdArg*(T: type InputFile, p: TaintedString): T =
except IOError:
raise newException(ValueError, "File not accessible")
result = T(p.string)
T(p.string)
proc parseCmdArg*(T: type TypedInputFile, p: TaintedString): T =
var path = p.string
proc parseCmdArg*(T: type TypedInputFile, p: string): T =
var path = p
when T.defaultExt.len > 0:
path = path.addFileExt(T.defaultExt)
@ -498,59 +498,59 @@ proc parseCmdArg*(T: type TypedInputFile, p: TaintedString): T =
except IOError:
raise newException(ValueError, "File not accessible")
result = T(path)
T(path)
proc parseCmdArg*(T: type[OutDir|OutFile|OutPath], p: TaintedString): T =
result = T(p)
func parseCmdArg*(T: type[OutDir|OutFile|OutPath], p: string): T =
T(p)
proc parseCmdArg*[T](_: type Option[T], s: TaintedString): Option[T] =
return some(parseCmdArg(T, s))
proc parseCmdArg*[T](_: type Option[T], s: string): Option[T] =
some(parseCmdArg(T, s))
template parseCmdArg*(T: type string, s: TaintedString): string =
string s
template parseCmdArg*(T: type string, s: string): string =
s
proc parseCmdArg*(T: type SomeSignedInt, s: TaintedString): T =
func parseCmdArg*(T: type SomeSignedInt, s: string): T =
T parseBiggestInt(string s)
proc parseCmdArg*(T: type SomeUnsignedInt, s: TaintedString): T =
func parseCmdArg*(T: type SomeUnsignedInt, s: string): T =
T parseBiggestUInt(string s)
proc parseCmdArg*(T: type SomeFloat, p: TaintedString): T =
result = parseFloat(p)
func parseCmdArg*(T: type SomeFloat, p: string): T =
parseFloat(p)
proc parseCmdArg*(T: type bool, p: TaintedString): T =
func parseCmdArg*(T: type bool, p: string): T =
try:
result = p.len == 0 or parseBool(p)
p.len == 0 or parseBool(p)
except CatchableError:
raise newException(ValueError, "'" & p.string & "' is not a valid boolean value. Supported values are on/off, yes/no, true/false or 1/0")
proc parseCmdArg*(T: type enum, s: TaintedString): T =
func parseCmdArg*(T: type enum, s: string): T =
parseEnum[T](string(s))
proc parseCmdArgAux(T: type, s: TaintedString): T = # {.raises: [ValueError].} =
proc parseCmdArgAux(T: type, s: string): T = # {.raises: [ValueError].} =
# The parseCmdArg procs are allowed to raise only `ValueError`.
# If you have provided your own specializations, please handle
# all other exception types.
mixin parseCmdArg
parseCmdArg(T, s)
proc completeCmdArg*(T: type enum, val: TaintedString): seq[string] =
func completeCmdArg*(T: type enum, val: string): seq[string] =
for e in low(T)..high(T):
let as_str = $e
if startsWithIgnoreStyle(as_str, val):
result.add($e)
proc completeCmdArg*(T: type SomeNumber, val: TaintedString): seq[string] =
return @[]
func completeCmdArg*(T: type SomeNumber, val: string): seq[string] =
@[]
proc completeCmdArg*(T: type bool, val: TaintedString): seq[string] =
return @[]
func completeCmdArg*(T: type bool, val: string): seq[string] =
@[]
proc completeCmdArg*(T: type string, val: TaintedString): seq[string] =
return @[]
func completeCmdArg*(T: type string, val: string): seq[string] =
@[]
proc completeCmdArg*(T: type[InputFile|TypedInputFile|InputDir|OutFile|OutDir|OutPath],
val: TaintedString): seq[string] =
val: string): seq[string] =
when not defined(nimscript):
let (dir, name, ext) = splitFile(val)
let tail = name & ext
@ -581,36 +581,36 @@ proc completeCmdArg*(T: type[InputFile|TypedInputFile|InputDir|OutFile|OutDir|Ou
except OSError:
discard
proc completeCmdArg*[T](_: type seq[T], val: TaintedString): seq[string] =
return @[]
func completeCmdArg*[T](_: type seq[T], val: string): seq[string] =
@[]
proc completeCmdArg*[T](_: type Option[T], val: TaintedString): seq[string] =
proc completeCmdArg*[T](_: type Option[T], val: string): seq[string] =
mixin completeCmdArg
return completeCmdArg(type(T), val)
proc completeCmdArgAux(T: type, val: TaintedString): seq[string] =
proc completeCmdArgAux(T: type, val: string): seq[string] =
mixin completeCmdArg
return completeCmdArg(T, val)
template setField[T](loc: var T, val: Option[TaintedString], defaultVal: untyped) =
template setField[T](loc: var T, val: Option[string], defaultVal: untyped) =
type FieldType = type(loc)
loc = if isSome(val): parseCmdArgAux(FieldType, val.get)
else: FieldType(defaultVal)
template setField[T](loc: var seq[T], val: Option[TaintedString], defaultVal: untyped) =
template setField[T](loc: var seq[T], val: Option[string], defaultVal: untyped) =
if val.isSome:
loc.add parseCmdArgAux(type(loc[0]), val.get)
else:
type FieldType = type(loc)
loc = FieldType(defaultVal)
proc makeDefaultValue*(T: type): T =
func makeDefaultValue*(T: type): T =
discard
proc requiresInput*(T: type): bool =
func requiresInput*(T: type): bool =
not ((T is seq) or (T is Option) or (T is bool))
proc acceptsMultipleValues*(T: type): bool =
func acceptsMultipleValues*(T: type): bool =
T is seq
template debugMacroResult(macroName: string) {.dirty.} =
@ -651,7 +651,7 @@ proc generateFieldSetters(RecordType: NimNode): NimNode =
newCall(bindSym"acceptsMultipleValues", fixedFieldType))
result.add quote do:
proc `completerName`(val: TaintedString): seq[string] {.
proc `completerName`(val: string): seq[string] {.
nimcall
gcsafe
sideEffect
@ -659,7 +659,7 @@ proc generateFieldSetters(RecordType: NimNode): NimNode =
.} =
return completeCmdArgAux(`fixedFieldType`, val)
proc `setterName`(`configVar`: var `RecordType`, val: Option[TaintedString]) {.
proc `setterName`(`configVar`: var `RecordType`, val: Option[string]) {.
nimcall
gcsafe
sideEffect
@ -678,14 +678,14 @@ proc generateFieldSetters(RecordType: NimNode): NimNode =
result.add settersArray
debugMacroResult "Field Setters"
proc checkDuplicate(cmd: CmdInfo, opt: OptInfo, fieldName: NimNode) =
func checkDuplicate(cmd: CmdInfo, opt: OptInfo, fieldName: NimNode) =
for x in cmd.opts:
if opt.name == x.name:
error "duplicate name detected: " & opt.name, fieldName
if opt.abbr.len > 0 and opt.abbr == x.abbr:
error "duplicate abbr detected: " & opt.abbr, fieldName
proc validPath(path: var seq[CmdInfo], parent, node: CmdInfo): bool =
func validPath(path: var seq[CmdInfo], parent, node: CmdInfo): bool =
for x in parent.opts:
if x.kind != Discriminator: continue
for y in x.subCmds:
@ -697,7 +697,7 @@ proc validPath(path: var seq[CmdInfo], parent, node: CmdInfo): bool =
return true
false
proc findPath(parent, node: CmdInfo): seq[CmdInfo] =
func findPath(parent, node: CmdInfo): seq[CmdInfo] =
# find valid path from parent to node
result = newSeq[CmdInfo]()
doAssert validPath(result, parent, node)
@ -878,7 +878,7 @@ proc loadImpl[C, SecondarySources](
let confAddr = addr result
template applySetter(setterIdx: int, cmdLineVal: TaintedString) =
template applySetter(setterIdx: int, cmdLineVal: string) =
try:
fieldSetters[setterIdx][1](confAddr[], some(cmdLineVal))
inc fieldCounters[setterIdx]
@ -889,7 +889,7 @@ proc loadImpl[C, SecondarySources](
getCurrentExceptionMsg())
when hasCompletions:
template getArgCompletions(opt: OptInfo, prefix: TaintedString): seq[string] =
template getArgCompletions(opt: OptInfo, prefix: string): seq[string] =
fieldSetters[opt.idx][2](prefix)
template required(opt: OptInfo): bool =
@ -897,8 +897,8 @@ proc loadImpl[C, SecondarySources](
template activateCmd(discriminator: OptInfo, activatedCmd: CmdInfo) =
let cmd = activatedCmd
applySetter(discriminator.idx, if cmd.desc.len > 0: TaintedString(cmd.desc)
else: TaintedString(cmd.name))
applySetter(discriminator.idx, if cmd.desc.len > 0: cmd.desc
else: cmd.name)
activeCmds.add cmd
nextArgIdx = cmd.getNextArgIdx(-1)
@ -1070,7 +1070,7 @@ proc loadImpl[C, SecondarySources](
# there is nothing left to do here.
discard
elif opt.hasDefault:
fieldSetters[opt.idx][1](conf, none[TaintedString]())
fieldSetters[opt.idx][1](conf, none[string]())
elif opt.required:
fail "The required option '$1' was not specified" % [opt.name]
@ -1092,7 +1092,7 @@ template load*(
copyrightBanner, printUsage, quitOnFailure,
secondarySourcesRef, secondarySources)
proc defaults*(Configuration: type): Configuration =
func defaults*(Configuration: type): Configuration =
load(Configuration, cmdLine = @[], printUsage = false, quitOnFailure = false)
proc dispatchImpl(cliProcSym, cliArgs, loadArgs: NimNode): NimNode =
@ -1175,7 +1175,7 @@ macro cli*(args: varargs[untyped]): untyped =
debugMacroResult "CLI Code"
proc load*(f: TypedInputFile): f.ContentType =
func load*(f: TypedInputFile): f.ContentType =
when f.Format is Unspecified or f.ContentType is Unspecified:
{.fatal: "To use `InputFile.load`, please specify the Format and ContentType of the file".}

View File

@ -1,4 +1,4 @@
# Copyright 2018 Status Research & Development GmbH
# Copyright 2018-2022 Status Research & Development GmbH
# Parts taken from Nim's Runtime Library (c) Copyright 2015 Andreas Rumpf
type
@ -17,11 +17,11 @@ type
cmds: seq[string]
idx: int
kind*: CmdLineKind ## The detected command line token
key*, val*: TaintedString ## Key and value pair; the key is the option
key*, val*: string ## Key and value pair; the key is the option
## or the argument, and the value is not "" if
## the option was given a value
proc parseWord(s: string, i: int, w: var string,
func parseWord(s: string, i: int, w: var string,
delim: set[char] = {'\t', ' '}): int =
result = i
if result < s.len and s[result] == '\"':
@ -37,7 +37,7 @@ proc parseWord(s: string, i: int, w: var string,
add(w, s[result])
inc(result)
proc initOptParser*(cmds: seq[string], shortNoVal: set[char]={},
func initOptParser*(cmds: seq[string], shortNoVal: set[char]={},
longNoVal: seq[string] = @[];
allowWhitespaceAfterColon = true): OptParser =
result.pos = 0
@ -48,10 +48,10 @@ proc initOptParser*(cmds: seq[string], shortNoVal: set[char]={},
result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
result.cmds = cmds
result.kind = cmdEnd
result.key = TaintedString""
result.val = TaintedString""
result.key = ""
result.val = ""
proc handleShortOption(p: var OptParser; cmd: string) =
func handleShortOption(p: var OptParser; cmd: string) =
var i = p.pos
p.kind = cmdShortOption
if i < cmd.len:
@ -67,7 +67,7 @@ proc handleShortOption(p: var OptParser; cmd: string) =
inc(i)
p.inShortState = false
while i < cmd.len and cmd[i] in {'\t', ' '}: inc(i)
p.val = TaintedString substr(cmd, i)
p.val = substr(cmd, i)
p.pos = 0
inc p.idx
else:
@ -77,7 +77,7 @@ proc handleShortOption(p: var OptParser; cmd: string) =
p.pos = 0
inc p.idx
proc next*(p: var OptParser) =
func next*(p: var OptParser) =
## Parses the next token.
##
## ``p.kind`` describes what kind of token has been parsed. ``p.key`` and
@ -119,12 +119,12 @@ proc next*(p: var OptParser) =
inc p.idx
i = 0
if p.idx < p.cmds.len:
p.val = TaintedString p.cmds[p.idx].substr(i)
elif len(p.longNoVal) > 0 and p.key.string notin p.longNoVal and p.idx+1 < p.cmds.len:
p.val = TaintedString p.cmds[p.idx+1]
p.val = p.cmds[p.idx].substr(i)
elif len(p.longNoVal) > 0 and p.key notin p.longNoVal and p.idx+1 < p.cmds.len:
p.val = p.cmds[p.idx+1]
inc p.idx
else:
p.val = TaintedString""
p.val = ""
inc p.idx
p.pos = 0
else:
@ -132,11 +132,11 @@ proc next*(p: var OptParser) =
handleShortOption(p, p.cmds[p.idx])
else:
p.kind = cmdArgument
p.key = TaintedString p.cmds[p.idx]
p.key = p.cmds[p.idx]
inc p.idx
p.pos = 0
iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedString] =
iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: string] =
p.pos = 0
p.idx = 0
while true:
@ -146,7 +146,7 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedSt
iterator getopt*(cmds: seq[string],
shortNoVal: set[char]={}, longNoVal: seq[string] = @[]):
tuple[kind: CmdLineKind, key, val: TaintedString] =
tuple[kind: CmdLineKind, key, val: string] =
var p = initOptParser(cmds, shortNoVal=shortNoVal, longNoVal=longNoVal)
while true:
next(p)

View File

@ -1,5 +1,5 @@
import
options
std/options
type
ConfigurationError* = object of CatchableError
@ -21,15 +21,15 @@ type
SubCommandArgs* = distinct string
Flag* = object
name*: TaintedString
name*: string
FlagWithValue* = object
name*: TaintedString
value*: TaintedString
name*: string
value*: string
FlagWithOptionalValue* = object
name*: TaintedString
value*: Option[TaintedString]
name*: string
value*: Option[string]
Unspecified* = object
Txt* = object
@ -61,4 +61,3 @@ template implicitlySelectable* {.pragma.}
## to allow the value of the discriminator to be determined
## implicitly when the user specifies any of the sub-options
## that depend on the disciminator value.

View File

@ -4,14 +4,14 @@ export stewNet
export ValidIpAddress
func parseCmdArg*(T: type ValidIpAddress, s: TaintedString): T =
func parseCmdArg*(T: type ValidIpAddress, s: string): T =
ValidIpAddress.init(string s)
proc completeCmdArg*(T: type ValidIpAddress, val: TaintedString): seq[string] =
func completeCmdArg*(T: type ValidIpAddress, val: string): seq[string] =
# TODO: Maybe complete the local IP address?
return @[]
@[]
func parseCmdArg*(T: type Port, s: TaintedString): T =
func parseCmdArg*(T: type Port, s: string): T =
template fail =
raise newException(ValueError,
"The supplied port must be an integer value in the range 1-65535")
@ -25,6 +25,5 @@ func parseCmdArg*(T: type Port, s: TaintedString): T =
return Port(intVal)
proc completeCmdArg*(T: type Port, val: TaintedString): seq[string] =
return @[]
func completeCmdArg*(T: type Port, val: string): seq[string] =
@[]

View File

@ -120,11 +120,11 @@ type
func defaultDataDir(conf: TestConf): string =
discard
func parseCmdArg*(T: type GraffitiBytes, input: TaintedString): T
func parseCmdArg*(T: type GraffitiBytes, input: string): T
{.raises: [ValueError, Defect].} =
discard
func completeCmdArg*(T: type GraffitiBytes, input: TaintedString): seq[string] =
func completeCmdArg*(T: type GraffitiBytes, input: string): seq[string] =
@[]
func defaultAdminListenAddress*(conf: TestConf): ValidIpAddress =

View File

@ -13,11 +13,11 @@ type
desc: "La2"
name: "la2" }: specialint.SInt
proc parseCmdArg(T: type specialint.SInt, p: TaintedString): T =
func parseCmdArg(T: type specialint.SInt, p: string): T =
parseInt(string p).T
proc completeCmdArg(T: type specialint.SInt, val: TaintedString): seq[string] =
return @[]
func completeCmdArg(T: type specialint.SInt, val: string): seq[string] =
@[]
suite "Qualified Ident":
test "Qualified Ident":