Case fixes for network modules.

This commit is contained in:
Dominik Picheta 2014-08-30 11:59:08 +01:00
commit cff2a0c0b4
5 changed files with 129 additions and 126 deletions

View file

@ -8,21 +8,21 @@
import asyncdispatch, asyncnet, strutils, parseutils, os, times
from ftpclient import TFtpBase, EInvalidReply, TFtpEvent
from net import bufferSize
from ftpclient import FtpBaseObj, ReplyError, FtpEvent
from net import BufferSize
type
TAsyncFtpClient* = TFtpBase[PAsyncSocket]
PAsyncFtpClient* = ref TAsyncFtpClient
AsyncFtpClientObj* = FtpBaseObj[AsyncSocket]
AsyncFtpClient* = ref AsyncFtpClientObj
ProgressChangedProc* =
proc (total, progress: BiggestInt, speed: float):
PFuture[void] {.closure, gcsafe.}
Future[void] {.closure, gcsafe.}
proc expectReply(ftp: PAsyncFtpClient): PFuture[TaintedString] =
proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] =
result = ftp.csock.recvLine()
proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} =
proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
## Send a message to the server, and wait for a primary reply.
## ``\c\L`` is added for you.
await ftp.csock.send(m & "\c\L")
@ -31,11 +31,11 @@ proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} =
proc assertReply(received: TaintedString, expected: varargs[string]) =
for i in items(expected):
if received.string.startsWith(i): return
raise newException(EInvalidReply,
raise newException(ReplyError,
"Expected reply '$1' got: $2" %
[expected.join("' or '"), received.string])
proc pasv(ftp: PAsyncFtpClient) {.async.} =
proc pasv(ftp: AsyncFtpClient) {.async.} =
## Negotiate a data connection.
ftp.dsock = newAsyncSocket()
@ -46,13 +46,13 @@ proc pasv(ftp: PAsyncFtpClient) {.async.} =
var ip = nums[0.. -3]
var port = nums[-2.. -1]
var properPort = port[0].parseInt()*256+port[1].parseInt()
await ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
ftp.dsockConnected = True
await ftp.dsock.connect(ip.join("."), Port(properPort.toU16))
ftp.dsockConnected = true
proc normalizePathSep(path: string): string =
return replace(path, '\\', '/')
proc connect*(ftp: PAsyncFtpClient) {.async.} =
proc connect*(ftp: AsyncFtpClient) {.async.} =
## Connect to the FTP server specified by ``ftp``.
await ftp.csock.connect(ftp.address, ftp.port)
@ -69,21 +69,21 @@ proc connect*(ftp: PAsyncFtpClient) {.async.} =
if ftp.pass != "":
assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
proc pwd*(ftp: PAsyncFtpClient): PFuture[TaintedString] {.async.} =
proc pwd*(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
## Returns the current working directory.
let wd = await ftp.send("PWD")
assertReply wd, "257"
return wd.string.captureBetween('"').TaintedString # "
proc cd*(ftp: PAsyncFtpClient, dir: string) {.async.} =
proc cd*(ftp: AsyncFtpClient, dir: string) {.async.} =
## Changes the current directory on the remote FTP server to ``dir``.
assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250")
proc cdup*(ftp: PAsyncFtpClient) {.async.} =
proc cdup*(ftp: AsyncFtpClient) {.async.} =
## Changes the current directory to the parent of the current directory.
assertReply(await(ftp.send("CDUP")), "200")
proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} =
proc getLines(ftp: AsyncFtpClient): Future[string] {.async.} =
## Downloads text data in ASCII mode
result = ""
assert ftp.dsockConnected
@ -96,7 +96,7 @@ proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} =
assertReply(await(ftp.expectReply()), "226")
proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} =
proc listDirs*(ftp: AsyncFtpClient, dir = ""): Future[seq[string]] {.async.} =
## Returns a list of filenames in the given directory. If ``dir`` is "",
## the current directory is used. If ``async`` is true, this
## function will return immediately and it will be your job to
@ -107,13 +107,13 @@ proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} =
result = splitLines(await ftp.getLines())
proc existsFile*(ftp: PAsyncFtpClient, file: string): PFuture[bool] {.async.} =
proc existsFile*(ftp: AsyncFtpClient, file: string): Future[bool] {.async.} =
## Determines whether ``file`` exists.
var files = await ftp.listDirs()
for f in items(files):
if f.normalizePathSep == file.normalizePathSep: return true
proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} =
proc createDir*(ftp: AsyncFtpClient, dir: string, recursive = false){.async.} =
## Creates a directory ``dir``. If ``recursive`` is true, the topmost
## subdirectory of ``dir`` will be created first, following the secondmost...
## etc. this allows you to give a full path as the ``dir`` without worrying
@ -123,14 +123,14 @@ proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} =
else:
var reply = TaintedString""
var previousDirs = ""
for p in split(dir, {os.dirSep, os.altSep}):
for p in split(dir, {os.DirSep, os.AltSep}):
if p != "":
previousDirs.add(p)
reply = await ftp.send("MKD " & previousDirs)
previousDirs.add('/')
assertReply reply, "257"
proc chmod*(ftp: PAsyncFtpClient, path: string,
proc chmod*(ftp: AsyncFtpClient, path: string,
permissions: set[TFilePermission]) {.async.} =
## Changes permission of ``path`` to ``permissions``.
var userOctal = 0
@ -152,7 +152,7 @@ proc chmod*(ftp: PAsyncFtpClient, path: string,
assertReply(await(ftp.send("SITE CHMOD " & perm &
" " & path.normalizePathSep)), "200")
proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} =
proc list*(ftp: AsyncFtpClient, dir = ""): Future[string] {.async.} =
## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
## working directory.
await ftp.pasv()
@ -162,7 +162,7 @@ proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} =
result = await ftp.getLines()
proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} =
proc retrText*(ftp: AsyncFtpClient, file: string): Future[string] {.async.} =
## Retrieves ``file``. File must be ASCII text.
await ftp.pasv()
let reply = await ftp.send("RETR " & file.normalizePathSep)
@ -170,13 +170,13 @@ proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} =
result = await ftp.getLines()
proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt,
proc getFile(ftp: AsyncFtpClient, file: TFile, total: BiggestInt,
onProgressChanged: ProgressChangedProc) {.async.} =
assert ftp.dsockConnected
var progress = 0
var progressInSecond = 0
var countdownFut = sleepAsync(1000)
var dataFut = ftp.dsock.recv(bufferSize)
var dataFut = ftp.dsock.recv(BufferSize)
while ftp.dsockConnected:
await dataFut or countdownFut
if countdownFut.finished:
@ -191,20 +191,20 @@ proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt,
progress.inc(data.len)
progressInSecond.inc(data.len)
file.write(data)
dataFut = ftp.dsock.recv(bufferSize)
dataFut = ftp.dsock.recv(BufferSize)
else:
ftp.dsockConnected = False
ftp.dsockConnected = false
assertReply(await(ftp.expectReply()), "226")
proc defaultOnProgressChanged*(total, progress: BiggestInt,
speed: float): PFuture[void] {.nimcall,gcsafe.} =
speed: float): Future[void] {.nimcall,gcsafe.} =
## Default FTP ``onProgressChanged`` handler. Does nothing.
result = newFuture[void]()
#echo(total, " ", progress, " ", speed)
result.complete()
proc retrFile*(ftp: PAsyncFtpClient, file, dest: string,
proc retrFile*(ftp: AsyncFtpClient, file, dest: string,
onProgressChanged = defaultOnProgressChanged) {.async.} =
## Downloads ``file`` and saves it to ``dest``.
## The ``EvRetr`` event is passed to the specified ``handleEvent`` function
@ -215,14 +215,14 @@ proc retrFile*(ftp: PAsyncFtpClient, file, dest: string,
var reply = await ftp.send("RETR " & file.normalizePathSep)
assertReply reply, ["125", "150"]
if {'(', ')'} notin reply.string:
raise newException(EInvalidReply, "Reply has no file size.")
var fileSize: biggestInt
raise newException(ReplyError, "Reply has no file size.")
var fileSize: BiggestInt
if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
raise newException(EInvalidReply, "Reply has no file size.")
raise newException(ReplyError, "Reply has no file size.")
await getFile(ftp, destFile, fileSize, onProgressChanged)
proc doUpload(ftp: PAsyncFtpClient, file: TFile,
proc doUpload(ftp: AsyncFtpClient, file: TFile,
onProgressChanged: ProgressChangedProc) {.async.} =
assert ftp.dsockConnected
@ -231,7 +231,7 @@ proc doUpload(ftp: PAsyncFtpClient, file: TFile,
var progress = 0
var progressInSecond = 0
var countdownFut = sleepAsync(1000)
var sendFut: PFuture[void] = nil
var sendFut: Future[void] = nil
while ftp.dsockConnected:
if sendFut == nil or sendFut.finished:
progress.inc(data.len)
@ -255,7 +255,7 @@ proc doUpload(ftp: PAsyncFtpClient, file: TFile,
await countdownFut or sendFut
proc storeFile*(ftp: PAsyncFtpClient, file, dest: string,
proc storeFile*(ftp: AsyncFtpClient, file, dest: string,
onProgressChanged = defaultOnProgressChanged) {.async.} =
## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
## function asynchronously is recommended to view the progress of
@ -271,9 +271,9 @@ proc storeFile*(ftp: PAsyncFtpClient, file, dest: string,
await doUpload(ftp, destFile, onProgressChanged)
proc newAsyncFtpClient*(address: string, port = TPort(21),
user, pass = ""): PAsyncFtpClient =
## Creates a new ``PAsyncFtpClient`` object.
proc newAsyncFtpClient*(address: string, port = Port(21),
user, pass = ""): AsyncFtpClient =
## Creates a new ``AsyncFtpClient`` object.
new result
result.user = user
result.pass = pass
@ -284,7 +284,7 @@ proc newAsyncFtpClient*(address: string, port = TPort(21),
when isMainModule:
var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
proc main(ftp: PAsyncFtpClient) {.async.} =
proc main(ftp: AsyncFtpClient) {.async.} =
await ftp.connect()
echo await ftp.pwd()
echo await ftp.listDirs()