Remove deprecated stuff from stdlib (#14699)
* update to the latest Jester * remove deprecated procs from some stdlib modules * 'criterion' is not maintained anymore and relies on obsolete stuff
This commit is contained in:
parent
8619534293
commit
e7f280bd26
41 changed files with 155 additions and 519 deletions
27
tests/ccgbugs2/tinefficient_const_table.nim
Normal file
27
tests/ccgbugs2/tinefficient_const_table.nim
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
discard """
|
||||
output: '''a
|
||||
long
|
||||
list
|
||||
of
|
||||
words'''
|
||||
cmd: r"nim c --hints:on $options -d:release $file"
|
||||
ccodecheck: "! @'genericSeqAssign'"
|
||||
target: "c"
|
||||
"""
|
||||
|
||||
# bug #4354
|
||||
import tables
|
||||
import sets
|
||||
import strutils
|
||||
|
||||
#const FRUITS = ["banana", "apple", "grapes"]
|
||||
#let FRUITS = ["banana", "apple", "grapes"].toHashSet
|
||||
const FRUITS = {"banana":0, "apple":0, "grapes":0}.toTable
|
||||
|
||||
proc main() =
|
||||
let L = "a long list of words".split()
|
||||
for word in L:
|
||||
if word notin FRUITS:
|
||||
echo(word)
|
||||
|
||||
main()
|
||||
|
|
@ -79,9 +79,8 @@ block hashForHashedSet:
|
|||
let
|
||||
seq1 = "This is the test."
|
||||
seq2 = "the test is This."
|
||||
s1 = seq1.toSet()
|
||||
s2 = seq2.toSet()
|
||||
var hashSeq: seq[Hash] = @[]
|
||||
s1 = seq1.toHashSet()
|
||||
s2 = seq2.toHashSet()
|
||||
doAssert s1 == s2
|
||||
doAssert hash(s1) == hash(s2)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Copyright (C) 2015 Dominik Picheta
|
||||
# MIT License - Look at license.txt for details.
|
||||
import net, strtabs, re, tables, parseutils, os, strutils, uri,
|
||||
import net, strtabs, re, tables, os, strutils, uri,
|
||||
times, mimetypes, asyncnet, asyncdispatch, macros, md5,
|
||||
logging, httpcore, asyncfile, macrocache, json, options,
|
||||
strformat
|
||||
|
|
@ -23,6 +23,7 @@ export SameSite
|
|||
when useHttpBeast:
|
||||
import httpbeast except Settings, Request
|
||||
import options
|
||||
from nativesockets import close
|
||||
else:
|
||||
import asynchttpserver except Request
|
||||
|
||||
|
|
@ -72,14 +73,14 @@ type
|
|||
of RouteCode:
|
||||
data: ResponseData
|
||||
|
||||
const jesterVer = "0.4.0"
|
||||
const jesterVer = "0.4.3"
|
||||
|
||||
proc toStr(headers: Option[RawHeaders]): string =
|
||||
return $newHttpHeaders(headers.get(@({:})))
|
||||
|
||||
proc createHeaders(headers: RawHeaders): string =
|
||||
result = ""
|
||||
if headers != nil:
|
||||
if headers.len > 0:
|
||||
for header in headers:
|
||||
let (key, value) = header
|
||||
result.add(key & ": " & value & "\c\L")
|
||||
|
|
@ -98,22 +99,24 @@ proc unsafeSend(request: Request, content: string) =
|
|||
|
||||
proc send(
|
||||
request: Request, code: HttpCode, headers: Option[RawHeaders], body: string
|
||||
) =
|
||||
): Future[void] =
|
||||
when useHttpBeast:
|
||||
let h =
|
||||
if headers.isNone: ""
|
||||
else: headers.get().createHeaders
|
||||
request.getNativeReq.send(code, body, h)
|
||||
var fut = newFuture[void]()
|
||||
complete(fut)
|
||||
return fut
|
||||
else:
|
||||
# TODO: This may cause issues if we send too fast.
|
||||
asyncCheck request.getNativeReq.respond(
|
||||
return request.getNativeReq.respond(
|
||||
code, body, newHttpHeaders(headers.get(@({:})))
|
||||
)
|
||||
|
||||
proc statusContent(request: Request, status: HttpCode, content: string,
|
||||
headers: Option[RawHeaders]) =
|
||||
headers: Option[RawHeaders]): Future[void] =
|
||||
try:
|
||||
send(request, status, headers, content)
|
||||
result = send(request, status, headers, content)
|
||||
when not defined(release):
|
||||
logging.debug(" $1 $2" % [$status, toStr(headers)])
|
||||
except:
|
||||
|
|
@ -174,7 +177,11 @@ proc sendStaticIfExists(
|
|||
return Http403
|
||||
|
||||
let fileSize = getFileSize(p)
|
||||
let mimetype = req.settings.mimes.getMimetype(p.splitFile.ext[1 .. ^1])
|
||||
let ext = p.splitFile.ext
|
||||
let mimetype = req.settings.mimes.getMimetype(
|
||||
if ext.len > 0: ext[1 .. ^1]
|
||||
else: ""
|
||||
)
|
||||
if fileSize < 10_000_000: # 10 mb
|
||||
var file = readFile(p)
|
||||
|
||||
|
|
@ -183,18 +190,18 @@ proc sendStaticIfExists(
|
|||
# If the user has a cached version of this file and it matches our
|
||||
# version, let them use it
|
||||
if req.headers.hasKey("If-None-Match") and req.headers["If-None-Match"] == hashed:
|
||||
req.statusContent(Http304, "", none[RawHeaders]())
|
||||
await req.statusContent(Http304, "", none[RawHeaders]())
|
||||
else:
|
||||
req.statusContent(Http200, file, some(@({
|
||||
"Content-Type": mimetype,
|
||||
"ETag": hashed
|
||||
})))
|
||||
await req.statusContent(Http200, file, some(@({
|
||||
"Content-Type": mimetype,
|
||||
"ETag": hashed
|
||||
})))
|
||||
else:
|
||||
let headers = @({
|
||||
"Content-Type": mimetype,
|
||||
"Content-Length": $fileSize
|
||||
})
|
||||
req.statusContent(Http200, "", some(headers))
|
||||
await req.statusContent(Http200, "", some(headers))
|
||||
|
||||
var fileStream = newFutureStream[string]("sendStaticIfExists")
|
||||
var file = openAsync(p, fmRead)
|
||||
|
|
@ -216,13 +223,22 @@ proc sendStaticIfExists(
|
|||
# If we get to here then no match could be found.
|
||||
return Http404
|
||||
|
||||
proc close*(request: Request) =
|
||||
## Closes client socket connection.
|
||||
##
|
||||
## Routes using this procedure must enable raw mode.
|
||||
let nativeReq = request.getNativeReq()
|
||||
when useHttpBeast:
|
||||
nativeReq.forget()
|
||||
nativeReq.client.close()
|
||||
|
||||
proc defaultErrorFilter(error: RouteError): ResponseData =
|
||||
case error.kind
|
||||
of RouteException:
|
||||
let e = error.exc
|
||||
let traceback = getStackTrace(e)
|
||||
var errorMsg = e.msg
|
||||
if errorMsg.isNil: errorMsg = "(nil)"
|
||||
if errorMsg.len == 0: errorMsg = "(empty)"
|
||||
|
||||
let error = traceback & errorMsg
|
||||
logging.error(error)
|
||||
|
|
@ -295,9 +311,11 @@ proc handleFileRequest(
|
|||
jes.settings.staticDir / cgi.decodeUrl(req.pathInfo)
|
||||
)
|
||||
|
||||
# Verify that this isn't outside our static` dir.
|
||||
# Verify that this isn't outside our static dir.
|
||||
var status = Http400
|
||||
if path.splitFile.dir.startsWith(jes.settings.staticDir):
|
||||
let pathDir = path.splitFile.dir / ""
|
||||
let staticDir = jes.settings.staticDir / ""
|
||||
if pathDir.startsWith(staticDir):
|
||||
if existsDir(path):
|
||||
status = await sendStaticIfExists(
|
||||
req,
|
||||
|
|
@ -347,7 +365,7 @@ proc handleRequestSlow(
|
|||
not dispatchedError and respData.content.len == 0:
|
||||
respData = await dispatchError(jes, req, initRouteError(respData))
|
||||
|
||||
statusContent(
|
||||
await statusContent(
|
||||
req,
|
||||
respData.code,
|
||||
respData.content,
|
||||
|
|
@ -368,7 +386,7 @@ proc handleRequest(jes: Jester, httpReq: NativeRequest): Future[void] =
|
|||
if likely(jes.matchers.len == 1 and not jes.matchers[0].async):
|
||||
let respData = jes.matchers[0].syncProc(req)
|
||||
if likely(respData.matched):
|
||||
statusContent(
|
||||
return statusContent(
|
||||
req,
|
||||
respData.code,
|
||||
respData.content,
|
||||
|
|
@ -383,6 +401,8 @@ proc handleRequest(jes: Jester, httpReq: NativeRequest): Future[void] =
|
|||
let respDataFut = dispatchError(jes, req, initRouteError(exc))
|
||||
return handleRequestSlow(jes, req, respDataFut, true)
|
||||
|
||||
assert(not result.isNil, "Expected handleRequest to return a valid future.")
|
||||
|
||||
proc newSettings*(
|
||||
port = Port(5000), staticDir = getCurrentDir() / "public",
|
||||
appName = "", bindAddr = "", reusePort = false,
|
||||
|
|
@ -461,14 +481,19 @@ proc serve*(
|
|||
]
|
||||
)
|
||||
else:
|
||||
logging.info("Jester is making jokes at http://0.0.0.0:$1$2" %
|
||||
[$self.settings.port, self.settings.appName])
|
||||
when defined(windows):
|
||||
logging.info("Jester is making jokes at http://127.0.0.1:$1$2 (all interfaces)" %
|
||||
[$self.settings.port, self.settings.appName])
|
||||
else:
|
||||
logging.info("Jester is making jokes at http://0.0.0.0:$1$2" %
|
||||
[$self.settings.port, self.settings.appName])
|
||||
|
||||
var jes = self
|
||||
when useHttpBeast:
|
||||
run(
|
||||
proc (req: httpbeast.Request): Future[void] =
|
||||
result = handleRequest(jes, req),
|
||||
{.gcsafe.}:
|
||||
result = handleRequest(jes, req),
|
||||
httpbeast.initSettings(self.settings.port, self.settings.bindAddr)
|
||||
)
|
||||
else:
|
||||
|
|
@ -484,14 +509,6 @@ proc serve*(
|
|||
asyncCheck serveFut
|
||||
runForever()
|
||||
|
||||
template resp*(code: HttpCode,
|
||||
headers: openarray[tuple[key, value: string]],
|
||||
content: string): typed =
|
||||
## Sets ``(code, headers, content)`` as the response.
|
||||
bind TCActionSend, newHttpHeaders
|
||||
result = (TCActionSend, code, headers.newHttpHeaders.some(), content, true)
|
||||
break route
|
||||
|
||||
template setHeader(headers: var Option[RawHeaders], key, value: string): typed =
|
||||
bind isNone
|
||||
if isNone(headers):
|
||||
|
|
@ -509,6 +526,17 @@ template setHeader(headers: var Option[RawHeaders], key, value: string): typed =
|
|||
# Add key if it doesn't exist.
|
||||
headers = some(h & @({key: value}))
|
||||
|
||||
template resp*(code: HttpCode,
|
||||
headers: openarray[tuple[key, val: string]],
|
||||
content: string): typed =
|
||||
## Sets ``(code, headers, content)`` as the response.
|
||||
bind TCActionSend
|
||||
result = (TCActionSend, code, none[RawHeaders](), content, true)
|
||||
for header in headers:
|
||||
setHeader(result[2], header[0], header[1])
|
||||
break route
|
||||
|
||||
|
||||
template resp*(content: string, contentType = "text/html;charset=utf-8"): typed =
|
||||
## Sets ``content`` as the response; ``Http200`` as the status code
|
||||
## and ``contentType`` as the Content-Type.
|
||||
|
|
@ -687,7 +715,8 @@ proc daysForward*(days: int): DateTime =
|
|||
return getTime().utc + initTimeInterval(days = days)
|
||||
|
||||
template setCookie*(name, value: string, expires="",
|
||||
sameSite: SameSite=Lax): typed =
|
||||
sameSite: SameSite=Lax, secure = false,
|
||||
httpOnly = false, domain = "", path = "") =
|
||||
## Creates a cookie which stores ``value`` under ``name``.
|
||||
##
|
||||
## The SameSite argument determines the level of CSRF protection that
|
||||
|
|
@ -695,7 +724,7 @@ template setCookie*(name, value: string, expires="",
|
|||
## should protect you from most vulnerabilities. Note that this is only
|
||||
## supported by some browsers:
|
||||
## https://caniuse.com/#feat=same-site-cookie-attribute
|
||||
let newCookie = makeCookie(name, value, expires)
|
||||
let newCookie = makeCookie(name, value, expires, domain, path, secure, httpOnly, sameSite)
|
||||
if isSome(result[2]) and
|
||||
(let headers = result[2].get(); headers.toTable.hasKey("Set-Cookie")):
|
||||
result[2] = some(headers & @({"Set-Cookie": newCookie}))
|
||||
|
|
@ -703,9 +732,12 @@ template setCookie*(name, value: string, expires="",
|
|||
setHeader(result[2], "Set-Cookie", newCookie)
|
||||
|
||||
template setCookie*(name, value: string, expires: DateTime,
|
||||
sameSite: SameSite=Lax): typed =
|
||||
sameSite: SameSite=Lax, secure = false,
|
||||
httpOnly = false, domain = "", path = "") =
|
||||
## Creates a cookie which stores ``value`` under ``name``.
|
||||
setCookie(name, value, format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"))
|
||||
setCookie(name, value,
|
||||
format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"),
|
||||
sameSite, secure, httpOnly, domain, path)
|
||||
|
||||
proc normalizeUri*(uri: string): string =
|
||||
## Remove any trailing ``/``.
|
||||
|
|
@ -721,7 +753,10 @@ proc checkAction*(respData: var ResponseData): bool =
|
|||
of TCActionPass:
|
||||
result = false
|
||||
of TCActionNothing:
|
||||
assert(false)
|
||||
raise newException(
|
||||
ValueError,
|
||||
"Missing route action, did you forget to use `resp` in your route?"
|
||||
)
|
||||
|
||||
proc skipDo(node: NimNode): NimNode {.compiletime.} =
|
||||
if node.kind == nnkDo:
|
||||
|
|
@ -764,14 +799,14 @@ proc ctParsePattern(pattern, pathPrefix: string): NimNode {.compiletime.} =
|
|||
newStrLitNode(node.text),
|
||||
newIdentNode(if node.optional: "true" else: "false"))
|
||||
|
||||
template setDefaultResp*(): typed =
|
||||
template setDefaultResp*() =
|
||||
# TODO: bindSym this in the 'routes' macro and put it in each route
|
||||
bind TCActionNothing, newHttpHeaders
|
||||
result.action = TCActionNothing
|
||||
result.code = Http200
|
||||
result.content = ""
|
||||
|
||||
template declareSettings(): typed {.dirty.} =
|
||||
template declareSettings() {.dirty.} =
|
||||
when not declaredInScope(settings):
|
||||
var settings = newSettings()
|
||||
|
||||
|
|
@ -1299,7 +1334,7 @@ proc routesEx(name: string, body: NimNode): NimNode =
|
|||
for branch in exceptionBranches:
|
||||
stmts.add(newIfStmt(branch))
|
||||
errorHandlerProc[6][0][1][^1][1][1][0] = stmts
|
||||
if httpCodeBranches.len > 1:
|
||||
if httpCodeBranches.len != 0:
|
||||
var stmts = newStmtList()
|
||||
for branch in httpCodeBranches:
|
||||
stmts.add(newIfStmt(branch))
|
||||
|
|
@ -1313,7 +1348,7 @@ proc routesEx(name: string, body: NimNode): NimNode =
|
|||
# echo toStrLit(result)
|
||||
# echo treeRepr(result)
|
||||
|
||||
macro routes*(body: untyped): typed =
|
||||
macro routes*(body: untyped) =
|
||||
result = routesEx("match", body)
|
||||
let jesIdent = genSym(nskVar, "jes")
|
||||
let matchIdent = newIdentNode("match")
|
||||
|
|
@ -1329,13 +1364,13 @@ macro routes*(body: untyped): typed =
|
|||
serve(`jesIdent`)
|
||||
)
|
||||
|
||||
macro router*(name: untyped, body: untyped): typed =
|
||||
macro router*(name: untyped, body: untyped) =
|
||||
if name.kind != nnkIdent:
|
||||
error("Need an ident.", name)
|
||||
|
||||
routesEx($name.ident, body)
|
||||
routesEx(strVal(name), body)
|
||||
|
||||
macro settings*(body: untyped): typed =
|
||||
macro settings*(body: untyped) =
|
||||
#echo(treeRepr(body))
|
||||
expectKind(body, nnkStmtList)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Package
|
||||
|
||||
version = "0.4.0" # Be sure to update jester.jesterVer too!
|
||||
version = "0.4.3" # Be sure to update jester.jesterVer too!
|
||||
author = "Dominik Picheta"
|
||||
description = "A sinatra-like web framework for Nim."
|
||||
license = "MIT"
|
||||
|
|
@ -13,10 +13,10 @@ skipDirs = @["tests"]
|
|||
requires "nim >= 0.18.1"
|
||||
|
||||
when not defined(windows):
|
||||
requires "httpbeast >= 0.2.0"
|
||||
requires "httpbeast >= 0.2.2"
|
||||
|
||||
# For tests
|
||||
requires "asynctools"
|
||||
requires "https://github.com/timotheecour/asynctools#pr_fix_compilation"
|
||||
|
||||
task test, "Runs the test suite.":
|
||||
exec "nimble c -y -r tests/tester"
|
||||
exec "nimble c -y -r tests/tester"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ type
|
|||
proc parsePattern*(pattern: string): Pattern =
|
||||
result = @[]
|
||||
template addNode(result: var Pattern, theT: NodeType, theText: string,
|
||||
isOptional: bool): typed =
|
||||
isOptional: bool) =
|
||||
block:
|
||||
var newNode: Node
|
||||
newNode.typ = theT
|
||||
|
|
@ -120,7 +120,7 @@ proc match*(pattern: Pattern, s: string):
|
|||
if s.len != i:
|
||||
result.matched = false
|
||||
|
||||
when true:
|
||||
when isMainModule:
|
||||
let f = parsePattern("/show/@id/test/@show?/?")
|
||||
doAssert match(f, "/show/12/test/hallo/").matched
|
||||
doAssert match(f, "/show/2131726/test/jjjuuwąąss").matched
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ type
|
|||
JesterError* = object of Exception
|
||||
|
||||
proc parseUrlQuery*(query: string, result: var Table[string, string])
|
||||
{.deprecated: "use stdlib".} =
|
||||
{.deprecated: "use stdlib cgi/decodeData".} =
|
||||
var i = 0
|
||||
i = query.skip("?")
|
||||
while i < query.len()-1:
|
||||
|
|
@ -192,4 +192,3 @@ when false:
|
|||
var r = {:}.newStringTable
|
||||
parseUrlQuery("FirstName=Mickey", r)
|
||||
echo r
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ proc reqMethod*(req: Request): HttpMethod =
|
|||
req.req.httpMethod.get()
|
||||
else:
|
||||
req.req.reqMethod
|
||||
|
||||
proc reqMeth*(req: Request): HttpMethod {.deprecated.} =
|
||||
req.reqMethod
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ proc main =
|
|||
for ii in 0..50_000:
|
||||
#while true:
|
||||
var t = getTime()
|
||||
var g = t.getGMTime()
|
||||
var g = t.utc()
|
||||
#echo isOnStack(addr g)
|
||||
|
||||
if i mod 100 == 0:
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ proc build_help*(expected: seq[Tparameter_specification] = @[],
|
|||
|
||||
# First generate the joined version of input parameters in a list.
|
||||
var
|
||||
seen = initSet[string]()
|
||||
seen = initHashSet[string]()
|
||||
prefixes: seq[string] = @[]
|
||||
helps: seq[string] = @[]
|
||||
for key in keys:
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ when defined(DebugKeys):
|
|||
activeVehicle.body.setPos mouseToSpace())
|
||||
ingameClient.registerHandler(KeyY, down, proc() =
|
||||
const looloo = ["Asteroid1", "Asteroid2"]
|
||||
addObject(looloo[random(looloo.len)]))
|
||||
addObject(looloo[rand(looloo.len)]))
|
||||
ingameClient.registerHandler(KeyO, down, proc() =
|
||||
if objects.len == 0:
|
||||
echo "Objects is empty"
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ task "release", "release build":
|
|||
## zip up all the files and such or something useful here
|
||||
|
||||
task "testskel", "create skeleton test dir for testing":
|
||||
let dirname = "test-" & $random(5000)
|
||||
let dirname = "test-" & $rand(5000)
|
||||
removeDir dirName
|
||||
createDir dirName/"data/fnt"
|
||||
copyFile "data/fnt/LiberationMono-Regular", dirName/"data/fnt/LiberationMono-Regular.ttf"
|
||||
|
|
@ -133,7 +133,7 @@ task "download", "download game assets":
|
|||
else: ## this crashes, dunno why
|
||||
var
|
||||
z: TZipArchive
|
||||
destDir = getCurrentDir()/("unzip" & $random(5000))
|
||||
destDir = getCurrentDir()/("unzip" & $rand(5000))
|
||||
if not z.open(path, fmRead):
|
||||
echo "Could not open zip, bad download?"
|
||||
return
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ proc post*(database: Database, message: Message) =
|
|||
raise newException(ValueError, "Message has to be less than 140 characters.")
|
||||
|
||||
database.db.exec(sql"INSERT INTO Message VALUES (?, ?, ?);", #<2>
|
||||
message.username, $message.time.toSeconds().int, message.msg) #<3>
|
||||
message.username, $message.time.toUnix().int, message.msg) #<3>
|
||||
|
||||
proc follow*(database: Database, follower: User, user: User) =
|
||||
database.db.exec(sql"INSERT INTO Following VALUES (?, ?);",#<2>
|
||||
|
|
@ -90,4 +90,4 @@ proc findMessages*(database: Database, usernames: seq[string],
|
|||
"ORDER BY time DESC LIMIT " & $limit),
|
||||
usernames)
|
||||
for row in messages:
|
||||
result.add(Message(username: row[0], time: fromSeconds(row[1].parseInt), msg: row[2]))
|
||||
result.add(Message(username: row[0], time: fromUnix(row[1].parseInt), msg: row[2]))
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ routes:
|
|||
redirect(uri("/" & @"target"))
|
||||
|
||||
post "/login":
|
||||
setCookie("username", @"username", getTime().getGMTime() + 2.hours)
|
||||
setCookie("username", @"username", getTime().utc() + 2.hours)
|
||||
redirect("/")
|
||||
|
||||
post "/createMessage":
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#for message in messages:
|
||||
<div>
|
||||
<a href="/${message.username}">${message.username}</a>
|
||||
<span>${message.time.getGMTime().format("HH:mm MMMM d',' yyyy")}</span>
|
||||
<span>${message.time.utc().format("HH:mm MMMM d',' yyyy")}</span>
|
||||
<h3>${message.msg}</h3>
|
||||
</div>
|
||||
#end for
|
||||
|
|
|
|||
|
|
@ -60,15 +60,15 @@ block tcritbits:
|
|||
|
||||
|
||||
block testequivalence:
|
||||
doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3,4]), "equivalent or subset")
|
||||
doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3]), "equivalent or subset")
|
||||
doAssert((not(toSet(@[1,2,3]) <= toSet(@[1,2]))), "equivalent or subset")
|
||||
doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3,4]), "strict subset")
|
||||
doAssert((not(toSet(@[1,2,3]) < toSet(@[1,2,3]))), "strict subset")
|
||||
doAssert((not(toSet(@[1,2,3]) < toSet(@[1,2]))), "strict subset")
|
||||
doAssert((not(toSet(@[1,2,3]) == toSet(@[1,2,3,4]))), "==")
|
||||
doAssert(toSet(@[1,2,3]) == toSet(@[1,2,3]), "==")
|
||||
doAssert((not(toSet(@[1,2,3]) == toSet(@[1,2]))), "==")
|
||||
doAssert(toHashSet(@[1,2,3]) <= toHashSet(@[1,2,3,4]), "equivalent or subset")
|
||||
doAssert(toHashSet(@[1,2,3]) <= toHashSet(@[1,2,3]), "equivalent or subset")
|
||||
doAssert((not(toHashSet(@[1,2,3]) <= toHashSet(@[1,2]))), "equivalent or subset")
|
||||
doAssert(toHashSet(@[1,2,3]) <= toHashSet(@[1,2,3,4]), "strict subset")
|
||||
doAssert((not(toHashSet(@[1,2,3]) < toHashSet(@[1,2,3]))), "strict subset")
|
||||
doAssert((not(toHashSet(@[1,2,3]) < toHashSet(@[1,2]))), "strict subset")
|
||||
doAssert((not(toHashSet(@[1,2,3]) == toHashSet(@[1,2,3,4]))), "==")
|
||||
doAssert(toHashSet(@[1,2,3]) == toHashSet(@[1,2,3]), "==")
|
||||
doAssert((not(toHashSet(@[1,2,3]) == toHashSet(@[1,2]))), "==")
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ test "unittest multiple requires":
|
|||
require(true)
|
||||
|
||||
|
||||
import math, random
|
||||
import random
|
||||
from strutils import parseInt
|
||||
proc defectiveRobot() =
|
||||
case random(1..4)
|
||||
case rand(1..4)
|
||||
of 1: raise newException(OSError, "CANNOT COMPUTE!")
|
||||
of 2: discard parseInt("Hello World!")
|
||||
of 3: raise newException(IOError, "I can't do that Dave.")
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ block tgetast_typeliar:
|
|||
error("Assertion failed: " & $(`message`) & "\n" & `line`)
|
||||
return
|
||||
|
||||
macro assertOrReturn(condition: bool): typed =
|
||||
macro assertOrReturn(condition: bool) =
|
||||
var message : NimNode = newLit(condition.repr)
|
||||
# echo message
|
||||
result = getAst assertOrReturn2(condition, message)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ converter int2string(x: int): string = $x
|
|||
template wrap(body: typed): untyped =
|
||||
body
|
||||
|
||||
macro makeProc(): typed =
|
||||
macro makeProc() =
|
||||
# Make a template tree
|
||||
result = quote do:
|
||||
proc someProc* =
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@ const EXTENSIONMAP = {
|
|||
"c": @["*.c", "*.h"],
|
||||
}.toTable()
|
||||
|
||||
const EXTENSIONS = toSet(concat(toSeq(EXTENSIONMAP.values())))
|
||||
const EXTENSIONS = toHashSet(concat(toSeq(EXTENSIONMAP.values())))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ line: 11
|
|||
|
||||
import sets
|
||||
|
||||
let BUILTIN_NAMES = toSet(["int8", "int16", "int32", "int64"])
|
||||
let BUILTIN_NAMES = toHashSet(["int8", "int16", "int32", "int64"])
|
||||
|
||||
macro test*(): bool =
|
||||
echo "int64" notin BUILTIN_NAMES
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue