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
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)
- [``pdcurses``](https://github.com/lcrees/pdcurses)
- [``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
to write and test. The examples are tested as the last step of
@@ -263,4 +265,4 @@ bar()
import std / [strutils, os, osproc]
import someNimblePackage / [strutils, os]
```
```

View File

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

View File

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

View File

@@ -150,6 +150,31 @@ proc code*(response: Response | AsyncResponse): HttpCode
## corresponding ``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 =
## Retrieves the specified response's body.
##

View File

@@ -64,6 +64,9 @@
## socket.acceptAddr(client, 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.}
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
## accept will be called again.
assert(client != nil)
assert client.fd.int <= 0, "Client socket needs to be initialised with " &
"`new`, not `newSocket`."
let ret = accept(server.fd)
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) =
## 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
case token
of "d":

View File

@@ -666,6 +666,7 @@ const
CREATE_ALWAYS* = 2'i32
CREATE_NEW* = 1'i32
OPEN_EXISTING* = 3'i32
OPEN_ALWAYS* = 4'i32
FILE_BEGIN* = 0'i32
INVALID_SET_FILE_POINTER* = -1'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")
file.close()
file = openAsync(fn, fmWrite)
await file.write("test3")
await file.write("t3")
file.close()
file = openAsync(fn, fmRead)
let data = await file.readAll()
doAssert data == "test3"
doAssert data == "t3"
file.close()

View File

@@ -131,6 +131,10 @@ template parseTest(s, f, sExpected: string, ydExpected: int) =
echo parsed.yearday, " exp: ", ydExpected
check(parsed.yearday == ydExpected)
template parseTestExcp(s, f: string) =
expect ValueError:
let parsed = s.parse(f)
template parseTestTimeOnly(s, f, sExpected: string) =
check sExpected in $s.parse(f, utc())
@@ -281,6 +285,51 @@ suite "ttimes":
test "parseTest":
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":
proc staticOffset(offset: int): Timezone =
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/pcre"
webdoc: "wrappers/openssl"
webdoc: "wrappers/joyent_http_parser"
webdoc: "posix/posix;wrappers/odbcsql"
webdoc: "wrappers/libsvm.nim"