Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq 2018-02-20 01:16:09 +01:00
commit 1d1ba4481f
12 changed files with 99 additions and 233 deletions

View file

@ -104,6 +104,8 @@ This now needs to be written as:
- [``poly``](https://github.com/lcrees/polynumeric) - [``poly``](https://github.com/lcrees/polynumeric)
- [``pdcurses``](https://github.com/lcrees/pdcurses) - [``pdcurses``](https://github.com/lcrees/pdcurses)
- [``romans``](https://github.com/lcrees/romans) - [``romans``](https://github.com/lcrees/romans)
- [``libsvm``](https://github.com/nim-lang/libsvm_legacy)
- [``joyent_http_parser``](https://github.com/nim-lang/joyent_http_parser)
- Added ``system.runnableExamples`` to make examples in Nim's documentation easier - Added ``system.runnableExamples`` to make examples in Nim's documentation easier
to write and test. The examples are tested as the last step of to write and test. The examples are tested as the last step of

View file

@ -557,21 +557,10 @@ Database support
Network Programming and Internet Protocols Network Programming and Internet Protocols
------------------------------------------ ------------------------------------------
* `joyent_http_parser <joyent_http_parser.html>`_
Wrapper for the joyent's high-performance HTTP parser.
* `openssl <openssl.html>`_ * `openssl <openssl.html>`_
Wrapper for OpenSSL. Wrapper for OpenSSL.
Scientific computing
--------------------
* `libsvm <libsvm.html>`_
Low level wrapper for `lib svm <http://www.csie.ntu.edu.tw/~cjlin/libsvm/>`_.
Nimble Nimble
====== ======

View file

@ -50,22 +50,21 @@ when defined(windows) or defined(nimdoc):
case mode case mode
of fmRead, fmReadWriteExisting: of fmRead, fmReadWriteExisting:
OPEN_EXISTING OPEN_EXISTING
of fmAppend, fmReadWrite, fmWrite: of fmReadWrite, fmWrite:
if fileExists(filename): CREATE_ALWAYS
OPEN_EXISTING of fmAppend:
else: OPEN_ALWAYS
CREATE_NEW
else: else:
proc getPosixFlags(mode: FileMode): cint = proc getPosixFlags(mode: FileMode): cint =
case mode case mode
of fmRead: of fmRead:
result = O_RDONLY result = O_RDONLY
of fmWrite: of fmWrite:
result = O_WRONLY or O_CREAT result = O_WRONLY or O_CREAT or O_TRUNC
of fmAppend: of fmAppend:
result = O_WRONLY or O_CREAT or O_APPEND result = O_WRONLY or O_CREAT or O_APPEND
of fmReadWrite: of fmReadWrite:
result = O_RDWR or O_CREAT result = O_RDWR or O_CREAT or O_TRUNC
of fmReadWriteExisting: of fmReadWriteExisting:
result = O_RDWR result = O_RDWR
result = result or O_NONBLOCK result = result or O_NONBLOCK

View file

@ -150,6 +150,31 @@ proc code*(response: Response | AsyncResponse): HttpCode
## corresponding ``HttpCode``. ## corresponding ``HttpCode``.
return response.status[0 .. 2].parseInt.HttpCode return response.status[0 .. 2].parseInt.HttpCode
proc contentType*(response: Response | AsyncResponse): string =
## Retrieves the specified response's content type.
##
## This is effectively the value of the "Content-Type" header.
response.headers.getOrDefault("content-type")
proc contentLength*(response: Response | AsyncResponse): int =
## Retrieves the specified response's content length.
##
## This is effectively the value of the "Content-Length" header.
##
## A ``ValueError`` exception will be raised if the value is not an integer.
var contentLengthHeader = response.headers.getOrDefault("Content-Length")
return contentLengthHeader.parseInt()
proc lastModified*(response: Response | AsyncResponse): DateTime =
## Retrieves the specified response's last modified time.
##
## This is effectively the value of the "Last-Modified" header.
##
## Raises a ``ValueError`` if the parsing fails or the value is not a correctly
## formatted time.
var lastModifiedHeader = response.headers.getOrDefault("last-modified")
result = parse(lastModifiedHeader, "dd, dd MMM yyyy HH:mm:ss Z")
proc body*(response: Response): string = proc body*(response: Response): string =
## Retrieves the specified response's body. ## Retrieves the specified response's body.
## ##

View file

@ -64,6 +64,9 @@
## socket.acceptAddr(client, address) ## socket.acceptAddr(client, address)
## echo("Client connected from: ", address) ## echo("Client connected from: ", address)
## ##
## **Note:** The ``client`` variable is initialised with ``new Socket`` **not**
## ``newSocket()``. The difference is that the latter creates a new file
## descriptor.
{.deadCodeElim: on.} {.deadCodeElim: on.}
import nativesockets, os, strutils, parseutils, times, sets, options import nativesockets, os, strutils, parseutils, times, sets, options
@ -753,6 +756,8 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string,
## flag is specified then this error will not be raised and instead ## flag is specified then this error will not be raised and instead
## accept will be called again. ## accept will be called again.
assert(client != nil) assert(client != nil)
assert client.fd.int <= 0, "Client socket needs to be initialised with " &
"`new`, not `newSocket`."
let ret = accept(server.fd) let ret = accept(server.fd)
let sock = ret[0] let sock = ret[0]

View file

@ -933,6 +933,14 @@ proc `$`*(time: Time): string {.tags: [], raises: [], benign.} =
proc parseToken(dt: var DateTime; token, value: string; j: var int) = proc parseToken(dt: var DateTime; token, value: string; j: var int) =
## Helper of the parse proc to parse individual tokens. ## Helper of the parse proc to parse individual tokens.
# Overwrite system.`[]` to raise a ValueError on index out of bounds.
proc `[]`[T, U](s: string, x: HSlice[T, U]): string =
if x.a >= s.len or x.b >= s.len:
raise newException(ValueError, "Value is missing required tokens, got: " &
s)
return system.`[]`(s, x)
var sv: int var sv: int
case token case token
of "d": of "d":

View file

@ -666,6 +666,7 @@ const
CREATE_ALWAYS* = 2'i32 CREATE_ALWAYS* = 2'i32
CREATE_NEW* = 1'i32 CREATE_NEW* = 1'i32
OPEN_EXISTING* = 3'i32 OPEN_EXISTING* = 3'i32
OPEN_ALWAYS* = 4'i32
FILE_BEGIN* = 0'i32 FILE_BEGIN* = 0'i32
INVALID_SET_FILE_POINTER* = -1'i32 INVALID_SET_FILE_POINTER* = -1'i32
NO_ERROR* = 0'i32 NO_ERROR* = 0'i32

View file

@ -1,93 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
type
csize = int
HttpDataProc* = proc (a2: ptr HttpParser, at: cstring, length: csize): cint {.cdecl.}
HttpProc* = proc (a2: ptr HttpParser): cint {.cdecl.}
HttpMethod* = enum
HTTP_DELETE = 0, HTTP_GET, HTTP_HEAD, HTTP_POST, HTTP_PUT, HTTP_CONNECT,
HTTP_OPTIONS, HTTP_TRACE, HTTP_COPY, HTTP_LOCK, HTTP_MKCOL, HTTP_MOVE,
HTTP_PROPFIND, HTTP_PROPPATCH, HTTP_UNLOCK, HTTP_REPORT, HTTP_MKACTIVITY,
HTTP_CHECKOUT, HTTP_MERGE, HTTP_MSEARCH, HTTP_NOTIFY, HTTP_SUBSCRIBE,
HTTP_UNSUBSCRIBE, HTTP_PATCH
HttpParserType* = enum
HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH
ParserFlag* = enum
F_CHUNKED = 1 shl 0,
F_CONNECTION_KEEP_ALIVE = 1 shl 1,
F_CONNECTION_CLOSE = 1 shl 2,
F_TRAILING = 1 shl 3,
F_UPGRADE = 1 shl 4,
F_SKIPBODY = 1 shl 5
HttpErrNo* = enum
HPE_OK, HPE_CB_message_begin, HPE_CB_path, HPE_CB_query_string, HPE_CB_url,
HPE_CB_fragment, HPE_CB_header_field, HPE_CB_header_value,
HPE_CB_headers_complete, HPE_CB_body, HPE_CB_message_complete,
HPE_INVALID_EOF_STATE, HPE_HEADER_OVERFLOW, HPE_CLOSED_CONNECTION,
HPE_INVALID_VERSION, HPE_INVALID_STATUS, HPE_INVALID_METHOD,
HPE_INVALID_URL, HPE_INVALID_HOST, HPE_INVALID_PORT, HPE_INVALID_PATH,
HPE_INVALID_QUERY_STRING, HPE_INVALID_FRAGMENT, HPE_LF_EXPECTED,
HPE_INVALID_HEADER_TOKEN, HPE_INVALID_CONTENT_LENGTH,
HPE_INVALID_CHUNK_SIZE, HPE_INVALID_CONSTANT, HPE_INVALID_INTERNAL_STATE,
HPE_STRICT, HPE_UNKNOWN
HttpParser*{.pure, final, importc: "http_parser", header: "http_parser.h".} = object
typ {.importc: "type".}: char
flags {.importc: "flags".}: char
state*{.importc: "state".}: char
header_state*{.importc: "header_state".}: char
index*{.importc: "index".}: char
nread*{.importc: "nread".}: cint
content_length*{.importc: "content_length".}: int64
http_major*{.importc: "http_major".}: cshort
http_minor*{.importc: "http_minor".}: cshort
status_code*{.importc: "status_code".}: cshort
http_method*{.importc: "method".}: cshort
http_errno_bits {.importc: "http_errno".}: char
upgrade {.importc: "upgrade".}: bool
data*{.importc: "data".}: pointer
HttpParserSettings*{.pure, final, importc: "http_parser_settings", header: "http_parser.h".} = object
on_message_begin*{.importc: "on_message_begin".}: HttpProc
on_url*{.importc: "on_url".}: HttpDataProc
on_header_field*{.importc: "on_header_field".}: HttpDataProc
on_header_value*{.importc: "on_header_value".}: HttpDataProc
on_headers_complete*{.importc: "on_headers_complete".}: HttpProc
on_body*{.importc: "on_body".}: HttpDataProc
on_message_complete*{.importc: "on_message_complete".}: HttpProc
{.deprecated: [THttpMethod: HttpMethod, THttpParserType: HttpParserType,
TParserFlag: ParserFlag, THttpErrNo: HttpErrNo,
THttpParser: HttpParser, THttpParserSettings: HttpParserSettings].}
proc http_parser_init*(parser: var HttpParser, typ: HttpParserType){.
importc: "http_parser_init", header: "http_parser.h".}
proc http_parser_execute*(parser: var HttpParser,
settings: var HttpParserSettings, data: cstring,
len: csize): csize {.
importc: "http_parser_execute", header: "http_parser.h".}
proc http_should_keep_alive*(parser: var HttpParser): cint{.
importc: "http_should_keep_alive", header: "http_parser.h".}
proc http_method_str*(m: HttpMethod): cstring{.
importc: "http_method_str", header: "http_parser.h".}
proc http_errno_name*(err: HttpErrNo): cstring{.
importc: "http_errno_name", header: "http_parser.h".}
proc http_errno_description*(err: HttpErrNo): cstring{.
importc: "http_errno_description", header: "http_parser.h".}

View file

@ -1,117 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module is a low level wrapper for `libsvm`:idx:.
{.deadCodeElim: on.}
const
LIBSVM_VERSION* = 312
when defined(windows):
const svmdll* = "libsvm.dll"
elif defined(macosx):
const svmdll* = "libsvm.dylib"
else:
const svmdll* = "libsvm.so"
type
Node*{.pure, final.} = object
index*: cint
value*: cdouble
Problem*{.pure, final.} = object
L*: cint
y*: ptr cdouble
x*: ptr ptr Node
Type*{.size: sizeof(cint).} = enum
C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR
KernelType*{.size: sizeof(cint).} = enum
LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED
Parameter*{.pure, final.} = object
typ*: Type
kernelType*: KernelType
degree*: cint # for poly
gamma*: cdouble # for poly/rbf/sigmoid
coef0*: cdouble # for poly/sigmoid
# these are for training only
cache_size*: cdouble # in MB
eps*: cdouble # stopping criteria
C*: cdouble # for C_SVC, EPSILON_SVR and NU_SVR
nr_weight*: cint # for C_SVC
weight_label*: ptr cint # for C_SVC
weight*: ptr cdouble # for C_SVC
nu*: cdouble # for NU_SVC, ONE_CLASS, and NU_SVR
p*: cdouble # for EPSILON_SVR
shrinking*: cint # use the shrinking heuristics
probability*: cint # do probability estimates
{.deprecated: [Tnode: Node, Tproblem: Problem, Ttype: Type,
TKernelType: KernelType, Tparameter: Parameter].}
#
# svm_model
#
type
Model*{.pure, final.} = object
param*: Parameter # parameter
nr_class*: cint # number of classes, = 2 in regression/one class svm
L*: cint # total #SV
SV*: ptr ptr Node # SVs (SV[l])
sv_coef*: ptr ptr cdouble # coefficients for SVs in decision functions (sv_coef[k-1][l])
rho*: ptr cdouble # constants in decision functions (rho[k*(k-1)/2])
probA*: ptr cdouble # pariwise probability information
probB*: ptr cdouble # for classification only
label*: ptr cint # label of each class (label[k])
nSV*: ptr cint # number of SVs for each class (nSV[k])
# nSV[0] + nSV[1] + ... + nSV[k-1] = l
# XXX
free_sv*: cint # 1 if svm_model is created by svm_load_model
# 0 if svm_model is created by svm_train
{.deprecated: [TModel: Model].}
proc train*(prob: ptr Problem, param: ptr Parameter): ptr Model{.cdecl,
importc: "svm_train", dynlib: svmdll.}
proc cross_validation*(prob: ptr Problem, param: ptr Parameter, nr_fold: cint,
target: ptr cdouble){.cdecl,
importc: "svm_cross_validation", dynlib: svmdll.}
proc save_model*(model_file_name: cstring, model: ptr Model): cint{.cdecl,
importc: "svm_save_model", dynlib: svmdll.}
proc load_model*(model_file_name: cstring): ptr Model{.cdecl,
importc: "svm_load_model", dynlib: svmdll.}
proc get_svm_type*(model: ptr Model): cint{.cdecl, importc: "svm_get_svm_type",
dynlib: svmdll.}
proc get_nr_class*(model: ptr Model): cint{.cdecl, importc: "svm_get_nr_class",
dynlib: svmdll.}
proc get_labels*(model: ptr Model, label: ptr cint){.cdecl,
importc: "svm_get_labels", dynlib: svmdll.}
proc get_svr_probability*(model: ptr Model): cdouble{.cdecl,
importc: "svm_get_svr_probability", dynlib: svmdll.}
proc predict_values*(model: ptr Model, x: ptr Node, dec_values: ptr cdouble): cdouble{.
cdecl, importc: "svm_predict_values", dynlib: svmdll.}
proc predict*(model: ptr Model, x: ptr Node): cdouble{.cdecl,
importc: "svm_predict", dynlib: svmdll.}
proc predict_probability*(model: ptr Model, x: ptr Node,
prob_estimates: ptr cdouble): cdouble{.cdecl,
importc: "svm_predict_probability", dynlib: svmdll.}
proc free_model_content*(model_ptr: ptr Model){.cdecl,
importc: "svm_free_model_content", dynlib: svmdll.}
proc free_and_destroy_model*(model_ptr_ptr: ptr ptr Model){.cdecl,
importc: "svm_free_and_destroy_model", dynlib: svmdll.}
proc destroy_param*(param: ptr Parameter){.cdecl, importc: "svm_destroy_param",
dynlib: svmdll.}
proc check_parameter*(prob: ptr Problem, param: ptr Parameter): cstring{.
cdecl, importc: "svm_check_parameter", dynlib: svmdll.}
proc check_probability_model*(model: ptr Model): cint{.cdecl,
importc: "svm_check_probability_model", dynlib: svmdll.}
proc set_print_string_function*(print_func: proc (arg: cstring) {.cdecl.}){.
cdecl, importc: "svm_set_print_string_function", dynlib: svmdll.}

View file

@ -41,11 +41,11 @@ proc main() {.async.} =
await file.write("test2") await file.write("test2")
file.close() file.close()
file = openAsync(fn, fmWrite) file = openAsync(fn, fmWrite)
await file.write("test3") await file.write("t3")
file.close() file.close()
file = openAsync(fn, fmRead) file = openAsync(fn, fmRead)
let data = await file.readAll() let data = await file.readAll()
doAssert data == "test3" doAssert data == "t3"
file.close() file.close()

View file

@ -131,6 +131,10 @@ template parseTest(s, f, sExpected: string, ydExpected: int) =
echo parsed.yearday, " exp: ", ydExpected echo parsed.yearday, " exp: ", ydExpected
check(parsed.yearday == ydExpected) check(parsed.yearday == ydExpected)
template parseTestExcp(s, f: string) =
expect ValueError:
let parsed = s.parse(f)
template parseTestTimeOnly(s, f, sExpected: string) = template parseTestTimeOnly(s, f, sExpected: string) =
check sExpected in $s.parse(f, utc()) check sExpected in $s.parse(f, utc())
@ -281,6 +285,51 @@ suite "ttimes":
test "parseTest": test "parseTest":
runTimezoneTests() runTimezoneTests()
test "incorrect inputs: empty string":
parseTestExcp("", "yyyy-MM-dd")
test "incorrect inputs: year":
parseTestExcp("20-02-19", "yyyy-MM-dd")
test "incorrect inputs: month number":
parseTestExcp("2018-2-19", "yyyy-MM-dd")
test "incorrect inputs: month name":
parseTestExcp("2018-Fe", "yyyy-MMM-dd")
test "incorrect inputs: day":
parseTestExcp("2018-02-1", "yyyy-MM-dd")
test "incorrect inputs: day of week":
parseTestExcp("2018-Feb-Mo", "yyyy-MMM-ddd")
test "incorrect inputs: hour":
parseTestExcp("2018-02-19 1:30", "yyyy-MM-dd hh:mm")
test "incorrect inputs: minute":
parseTestExcp("2018-02-19 16:3", "yyyy-MM-dd hh:mm")
test "incorrect inputs: second":
parseTestExcp("2018-02-19 16:30:0", "yyyy-MM-dd hh:mm:ss")
test "incorrect inputs: timezone (z)":
parseTestExcp("2018-02-19 16:30:00 ", "yyyy-MM-dd hh:mm:ss z")
test "incorrect inputs: timezone (zz) 1":
parseTestExcp("2018-02-19 16:30:00 ", "yyyy-MM-dd hh:mm:ss zz")
test "incorrect inputs: timezone (zz) 2":
parseTestExcp("2018-02-19 16:30:00 +1", "yyyy-MM-dd hh:mm:ss zz")
test "incorrect inputs: timezone (zzz) 1":
parseTestExcp("2018-02-19 16:30:00 ", "yyyy-MM-dd hh:mm:ss zzz")
test "incorrect inputs: timezone (zzz) 2":
parseTestExcp("2018-02-19 16:30:00 +01:", "yyyy-MM-dd hh:mm:ss zzz")
test "incorrect inputs: timezone (zzz) 3":
parseTestExcp("2018-02-19 16:30:00 +01:0", "yyyy-MM-dd hh:mm:ss zzz")
test "dynamic timezone": test "dynamic timezone":
proc staticOffset(offset: int): Timezone = proc staticOffset(offset: int): Timezone =
proc zoneInfoFromTz(adjTime: Time): ZonedTime = proc zoneInfoFromTz(adjTime: Time): ZonedTime =

View file

@ -77,7 +77,5 @@ webdoc: "wrappers/mysql;wrappers/iup"
webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc;wrappers/odbcsql" webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc;wrappers/odbcsql"
webdoc: "wrappers/pcre" webdoc: "wrappers/pcre"
webdoc: "wrappers/openssl" webdoc: "wrappers/openssl"
webdoc: "wrappers/joyent_http_parser"
webdoc: "posix/posix;wrappers/odbcsql" webdoc: "posix/posix;wrappers/odbcsql"
webdoc: "wrappers/libsvm.nim"