Skip to content

Commit

Permalink
Add docstring support to @agent (#717)
Browse files Browse the repository at this point in the history
* Added docstring support to @agent

Fixes issue #715. With thanks to Michael Hatherly!

* Removed separate `@doc` calls with `@agent`

`@agent` can now take a docstring directly, instead of relying on an
additional call to `@doc`.

* Removed superflous `Core.@__doc__`

* Removed superfluous comment

* Added test for docstring capture

* Bumped patch number
  • Loading branch information
veddox committed Dec 21, 2022
1 parent 6a8bbe5 commit 2e2d921
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Agents"
uuid = "46ada45e-f475-11e8-01d0-f70cc89e6671"
authors = ["George Datseris", "Tim DuBois", "Aayush Sabharwal", "Ali Vahdati"]
version = "5.6.2"
version = "5.6.3"

[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Expand Down
10 changes: 8 additions & 2 deletions src/core/agents.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ that the resulting new agent type will have.
The `id` is an unchangable field (and in Julia versions ≥ v1.8 this is enforced).
Use functions like [`move_agent!`](@ref) etc., to change the position.
You can use the `@doc` macro from Julia to document the generated struct if you wish so.
## Examples
### Example without optional hierarchy
Using
Expand Down Expand Up @@ -197,8 +195,13 @@ macro agent(new_name, base_type, extra_fields)
# It is important to evaluate the macro in the module that it was called at
Core.eval($(__module__), expr)
end
# allow attaching docstrings to the new struct, issue #715
Core.@__doc__($(esc(Docs.namify(new_name))))
nothing
end
end


# TODO: I do not know how to merge these two macros to remove code duplication.
# There should be away that only the 4-argument version is used
# and the 3-argument version just passes `AbstractAgent` to the 4-argument.
Expand Down Expand Up @@ -234,6 +237,9 @@ macro agent(new_name, base_type, super_type, extra_fields)
# It is important to evaluate the macro in the module that it was called at
Core.eval($(__module__), expr)
end
# allow attaching docstrings to the new struct, issue #715
Core.@__doc__($(esc(Docs.namify(new_name))))
nothing
end
end

Expand Down
13 changes: 6 additions & 7 deletions src/spaces/continuous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,16 @@ function Base.show(io::IO, space::ContinuousSpace{D,P}) where {D,P}
print(io, s)
end

@agent ContinuousAgent{D} NoSpaceAgent begin
pos::NTuple{D,Float64}
vel::NTuple{D,Float64}
end

@doc """
"""
ContinuousAgent{D} <: AbstractAgent
The minimal agent struct for usage with `D`-dimensional [`ContinuousSpace`](@ref).
It has the additoinal fields `pos::NTuple{D,Float64}, vel::NTuple{D,Float64}`.
See also [`@agent`](@ref).
""" ContinuousAgent
"""
@agent ContinuousAgent{D} NoSpaceAgent begin
pos::NTuple{D,Float64}
vel::NTuple{D,Float64}
end

"""
ContinuousSpace(extent::NTuple{D, <:Real}; kwargs...)
Expand Down
13 changes: 6 additions & 7 deletions src/spaces/graph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,14 @@ function Base.show(io::IO, s::GraphSpace)
print(io, "GraphSpace with $(nv(s.graph)) positions and $(ne(s.graph)) edges")
end

@agent GraphAgent NoSpaceAgent begin
pos::Int
end

@doc """
"""
GraphAgent <: AbstractAgent
The minimal agent struct for usage with [`GraphSpace`](@ref).
It has an additional `pos::Int` field. See also [`@agent`](@ref).
""" GraphAgent
"""
@agent GraphAgent NoSpaceAgent begin
pos::Int
end

#######################################################################################
# Agents.jl space API
Expand Down Expand Up @@ -205,4 +204,4 @@ Graphs.add_edge!(model::ABM{<:GraphSpace}, args...; kwargs...) = add_edge!(model
Remove an edge (relationship between two positions) from the graph.
Returns a boolean, true if the operation was successful.
"""
Graphs.rem_edge!(model::ABM{<:GraphSpace}, n, m) = rem_edge!(model.space.graph, n, m)
Graphs.rem_edge!(model::ABM{<:GraphSpace}, n, m) = rem_edge!(model.space.graph, n, m)
11 changes: 5 additions & 6 deletions src/spaces/grid_general.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ to vector of indices within each radius.
"""
abstract type AbstractGridSpace{D,P} <: DiscreteSpace end

@agent GridAgent{D} NoSpaceAgent begin
pos::NTuple{D, Int}
end

@doc """
"""
GridAgent{D} <: AbstractAgent
The minimal agent struct for usage with `D`-dimensional [`GridSpace`](@ref).
It has an additional `pos::NTuple{D,Int}` field. See also [`@agent`](@ref).
""" GridAgent
"""
@agent GridAgent{D} NoSpaceAgent begin
pos::NTuple{D, Int}
end

function positions(space::AbstractGridSpace)
x = CartesianIndices(space.stored_ids)
Expand Down
12 changes: 6 additions & 6 deletions src/spaces/openstreetmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,14 @@ function Base.show(io::IO, s::OpenStreetMapSpace)
)
end

@agent OSMAgent NoSpaceAgent begin
pos::Tuple{Int,Int,Float64}
end
@doc """
"""
OSMAgent <: AbstractAgent
The minimal agent struct for usage with [`OpenStreetMapSpace`](@ref).
It has an additional field `pos::Tuple{Int,Int,Float64}`. See also [`@agent`](@ref).
""" OSMAgent
"""
@agent OSMAgent NoSpaceAgent begin
pos::Tuple{Int,Int,Float64}
end

"""
OSM.test_map()
Expand Down Expand Up @@ -1011,4 +1011,4 @@ end # module OSM
# These are for aliasing the in-module names, and exporting them at top level
const OpenStreetMapSpace = OSM.OpenStreetMapSpace
const OSMSpace = OSM.OpenStreetMapSpace
const OSMAgent = OSM.OSMAgent
const OSMAgent = OSM.OSMAgent
4 changes: 4 additions & 0 deletions test/model_creation_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ using Test, Agents, Random
@test fieldnames(A3) == (:id, :pos, :weight)
@test fieldtypes(A3) == (Int, NTuple{2, Int}, Float64)

"""
This is a test docstring for agent A4
"""
@agent A4 A3 begin
z::Bool
end
@test A4 <: AbstractAgent
@test fieldnames(A4) == (:id, :pos, :weight, :z)
@test fieldtypes(A4) == (Int, NTuple{2, Int}, Float64, Bool)
@test contains(string(@doc(A4)), "This is a test docstring for agent A4")

# Also test subtyping
abstract type AbstractHuman <: AbstractAgent end
Expand Down

0 comments on commit 2e2d921

Please sign in to comment.