Skip to content

Commit

Permalink
Merge 9d1f8d2 into d28ccc8
Browse files Browse the repository at this point in the history
  • Loading branch information
Tieske committed Jan 9, 2023
2 parents d28ccc8 + 9d1f8d2 commit 01662ef
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 24 deletions.
85 changes: 85 additions & 0 deletions bin/copas.lua
@@ -0,0 +1,85 @@
#!/usr/bin/env lua

-- luacheck: globals copas
copas = require("copas")


-- Error handler that forces an application exit
local function errorhandler(err, co, skt)
io.stderr:write(copas.gettraceback(err, co, skt).."\n")
os.exit(1)
end


local function version_info()
print(copas._VERSION, copas._COPYRIGHT)
print(copas._DESCRIPTION)
print("Lua VM:", _G._VERSION)
end


local function load_lib(lib_name)
require(lib_name)
end


local function run_code(code)
if loadstring then -- deprecated in Lua 5.2
assert(loadstring(code, "command line"))()
else
assert(load(code, "command line"))()
end
end


local function run_stdin()
assert(loadfile())()
end


local function run_file(filename, i)
-- shift arguments, such that the Lua file being executed is at index 0. The
-- first argument following the name is at index 1.
local last = #arg
local first = #arg
for idx, v in pairs(arg) do
if idx < first then first = idx end
end
for n = first - i, last do
arg[n] = arg[n+i] -- luacheck: ignore
end
assert(loadfile(filename))()
end


local function show_usage()
print([[
usage: copas [options]... [script [args]...].
Available options are:
-e chunk Execute string 'chunk'.
-l name Require library 'name'.
-v Show version information.
-- Stop handling options.
- Execute stdin and stop handling options.]])
os.exit(1)
end


copas(function()
copas.seterrorhandler(errorhandler)
local i = 0
while i < math.max(#arg, 1) do -- if no args, use 1 being 'nil'
i = i + 1
local handled = false
local opt = arg[i] or "-" -- set default action if no args
-- options to continue handling
if opt == "-v" then version_info() handled = true end
if opt == "-l" then i = i + 1 load_lib(arg[i]) handled = true end
if opt == "-e" then i = i + 1 run_code(arg[i]) handled = true end
-- options that terminate handling
if opt == "--" then return end
if opt == "-" then return run_stdin() end
if opt:sub(1,1) == "-" and not handled then return show_usage() end
if not handled then return run_file(opt, i) end
end
end)
5 changes: 5 additions & 0 deletions copas-cvs-6.rockspec
Expand Up @@ -35,6 +35,11 @@ dependencies = {
}
build = {
type = "builtin",
install = {
bin = {
copas = "bin/copas.lua",
}
},
modules = {
["copas"] = "src/copas.lua",
["copas.http"] = "src/copas/http.lua",
Expand Down
2 changes: 2 additions & 0 deletions docs/index.html
Expand Up @@ -104,6 +104,8 @@ <h2><a name="history"></a>History</h2>
<dd><ul>
<li>Fix: windows makefile didn't include all submodules.</li>
<li>Fix: creating a new timer with a bad delay setting would throw a bad error message.</li>
<li>Refactor: submodules are now part of copas (lazily loaded) and do not need to be required anymore</li>
<li>Feat: runtime script added to directly run copas based code</li>
</ul></dd>

<dt><strong>Copas 4.6.0</strong> [30/Dec/2022]</dt>
Expand Down
31 changes: 27 additions & 4 deletions docs/manual.html
Expand Up @@ -55,6 +55,31 @@ <h2><a name="install"></a>Installing</h2>
<p>Note: LuaSec is not automatically installed as a dependency. If you want to use ssl with Copas,
you need to manually install LuaSec as well.</p>

<h2><a name="cli"></a>Runtime</h2>

Copas can either be used as a regular Lua library, or as a runtime. A command line script that
acts as a runtime engine is included.

When using the runtime, the library is available as a global (<code>copas</code>), and the
scheduler will automatically be started. For example:

<pre class="example">
#!/usr/bin/env copas

local count = 0
copas.timer.new {
delay = 1,
recurring = true,
callback = function(self)
count = count + 1
print('hello world ' .. count)
if count >= 5 then
self:cancel()
end
end
}
</pre>

<h2><a name="introduction"></a>Introduction to Copas</h2>

<p>
Expand Down Expand Up @@ -345,10 +370,9 @@ <h2><a name="timers"></a>Creating timers</h2>
Below an example of a timer;</p>
<pre class="example">
local copas = require("copas")
local timer = require("copas.timer")

copas(function()
timer.new({
copas.timer.new({
delay = 1, -- delay in seconds
recurring = true, -- make the timer repeat
params = "hello world",
Expand All @@ -370,9 +394,8 @@ <h2><a name="synchronization"></a>Synchronization primitives</h2>
</p>
<pre class="example">
local copas = require("copas")
local new_lock = require("copas.lock").new

local lock = new_lock()
local lock = copas.lock.new()

local function some_func()
local ok, err, wait = lock:get()
Expand Down
10 changes: 5 additions & 5 deletions docs/reference.html
Expand Up @@ -427,7 +427,7 @@ <h3>Non-blocking data exchange and timer/sleep functions</h3>
be "timeout".
</dd>

<dt><strong><code>lock.new([timeout], [not_reentrant])</code></strong></dt>
<dt><strong><code>copas.lock.new([timeout], [not_reentrant])</code></strong></dt>
<dd>Creates and returns a new lock. The <code>timeout</code> specifies the
default timeout for the lock in seconds, and defaults to 10 (set it to <code>math.huge</code>
to wait forever). By default the lock is re-entrant,
Expand Down Expand Up @@ -476,10 +476,10 @@ <h3>Non-blocking data exchange and timer/sleep functions</h3>
</dd>

<dt><strong><code>queue.name</code></strong></dt>
<dd>A field set to name of the queue. See <code>queue.new()</code>.
<dd>A field set to name of the queue. See <code>copas.queue.new()</code>.
</dd>

<dt><strong><code>queue.new([options])</code></strong></dt>
<dt><strong><code>copas.queue.new([options])</code></strong></dt>
<dd>Creates and returns a new queue. The <code>options</code> table has the following
fields:
<ul>
Expand Down Expand Up @@ -535,7 +535,7 @@ <h3>Non-blocking data exchange and timer/sleep functions</h3>
maximum. In that case the result will be <code>nil + "too many"</code>.
</dd>

<dt><strong><code>semaphore.new(max, [start], [timeout])</code></strong></dt>
<dt><strong><code>copas.semaphore.new(max, [start], [timeout])</code></strong></dt>
<dd>Creates and returns a new semaphore (fifo).
<code>max</code> specifies the maximum number of resources the semaphore can hold.
The optional <code>start</code> parameter (default 0) specifies the number of resources upon creation.
Expand All @@ -556,7 +556,7 @@ <h3>Non-blocking data exchange and timer/sleep functions</h3>
resources are requested than maximum available the error will be <code>"too many"</code>.
</dd>

<dt><strong><code>timer.new(options)</code></strong></dt>
<dt><strong><code>copas.timer.new(options)</code></strong></dt>
<dd>Creates and returns an (armed) timer object. The <code>options</code> table has the following fields;
<ul>
<li><code>options.name</code> (optional): the name for the timer, the default name will be
Expand Down
2 changes: 1 addition & 1 deletion misc/testasyncspeed.lua
@@ -1,6 +1,6 @@
local copas = require("copas")
local synchttp = require("socket.http").request
local asynchttp = require("copas.http").request
local asynchttp = copas.http.request
local gettime = require("socket").gettime

local targets = {
Expand Down
27 changes: 22 additions & 5 deletions src/copas.lua
Expand Up @@ -92,11 +92,28 @@ do
end


local copas = setmetatable({},{
__call = function(self, ...)
return self.loop(...)
end,
})
-- Setup the Copas meta table to auto-load submodules and define a default method
local copas do
local submodules = { "ftp", "http", "lock", "queue", "semaphore", "smtp", "timer" }
for i, key in ipairs(submodules) do
submodules[key] = true
submodules[i] = nil
end

copas = setmetatable({},{
__index = function(self, key)
if submodules[key] then
self[key] = require("copas."..key)
submodules[key] = nil
return rawget(self, key)
end
end,
__call = function(self, ...)
return self.loop(...)
end,
})
end


-- Meta information is public even if beginning with an "_"
copas._COPYRIGHT = "Copyright (C) 2005-2013 Kepler Project, 2015-2023 Thijs Schreijer"
Expand Down
4 changes: 2 additions & 2 deletions src/copas/queue.lua
@@ -1,6 +1,6 @@
local copas = require "copas"
local Sema = require "copas.semaphore"
local Lock = require "copas.lock"
local Sema = copas.semaphore
local Lock = copas.lock


local Queue = {}
Expand Down
2 changes: 1 addition & 1 deletion tests/http-timeout.lua
Expand Up @@ -6,7 +6,7 @@
local copas = require 'copas'
local socket = require 'socket'
local ltn12 = require 'ltn12'
local request = require("copas.http").request
local request = copas.http.request

-- copas.debug.start()

Expand Down
2 changes: 1 addition & 1 deletion tests/httpredirect.lua
@@ -1,7 +1,7 @@
-- test redirecting http <-> https combinations

local copas = require("copas")
local http = require("copas.http")
local http = copas.http
local ltn12 = require("ltn12")
local dump_all_headers = false
local redirect
Expand Down
2 changes: 1 addition & 1 deletion tests/lock.lua
Expand Up @@ -4,7 +4,7 @@ package.path = string.format("../src/?.lua;%s", package.path)


local copas = require "copas"
local Lock = require "copas.lock"
local Lock = copas.lock
local gettime = require("socket").gettime

local test_complete = false
Expand Down
2 changes: 1 addition & 1 deletion tests/queue.lua
Expand Up @@ -4,7 +4,7 @@ local now = require("socket").gettime


local copas = require "copas"
local Queue = require "copas.queue"
local Queue = copas.queue



Expand Down
2 changes: 1 addition & 1 deletion tests/request.lua
@@ -1,5 +1,5 @@
local copas = require("copas")
local http = require("copas.http")
local http = copas.http

local url = assert(arg[1], "missing url argument")
local debug_mode = not not arg[2]
Expand Down
2 changes: 1 addition & 1 deletion tests/semaphore.lua
Expand Up @@ -4,7 +4,7 @@ local now = require("socket").gettime


local copas = require "copas"
local semaphore = require "copas.semaphore"
local semaphore = copas.semaphore



Expand Down
2 changes: 1 addition & 1 deletion tests/timer.lua
Expand Up @@ -5,7 +5,7 @@ package.path = string.format("../src/?.lua;%s", package.path)

local copas = require "copas"
local gettime = require("socket").gettime
local timer = require "copas.timer"
local timer = copas.timer

local successes = 0

Expand Down

0 comments on commit 01662ef

Please sign in to comment.