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:
Miran 2020-06-17 15:25:02 +02:00 • committed by GitHub
commit e7f280bd26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 155 additions and 519 deletions

View 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()

View file

@ -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)

View file

@ -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)

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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:

View file

@ -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"

View file

@ -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

View file

@ -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]))

View file

@ -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":

View file

@ -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

View file

@ -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]))), "==")

View file

@ -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.")

View file

@ -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)

View file

@ -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* =

View file

@ -10,4 +10,4 @@ const EXTENSIONMAP = {
"c": @["*.c", "*.h"],
}.toTable()
const EXTENSIONS = toSet(concat(toSeq(EXTENSIONMAP.values())))
const EXTENSIONS = toHashSet(concat(toSeq(EXTENSIONMAP.values())))

View file

@ -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