Skip to content

general updates #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: tests

on:
push:
branches:
- '*'
pull_request:
branches:
- '*'

jobs:
runtests:
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: ['1.0', '1.10', 'nightly']
julia-arch: [x64, x86]
os: [ubuntu-latest, windows-latest, macOS-latest]
exclude:
- os: macOS-latest
julia-arch: x86
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Files generated by invoking Julia with --code-coverage
*.jl.cov
*.jl.*.cov

# Files generated by invoking Julia with --track-allocation
*.jl.mem

# System-specific files and directories generated by the BinaryProvider and BinDeps packages
# They contain absolute paths specific to the host computer, and so should not be committed
deps/deps.jl
deps/build.log
deps/downloads/
deps/usr/
deps/src/

# Build artifacts for creating documentation generated by the Documenter package
docs/build/
docs/site/

# File generated by Pkg, the package manager, based on a corresponding Project.toml
# It records a fixed state of all packages used by the project. As such, it should not be
# committed for packages, but should be committed for applications that require a static
# environment.
Manifest.toml
27 changes: 0 additions & 27 deletions .travis.yml

This file was deleted.

11 changes: 7 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
name = "ReadOnlyArrays"
uuid = "988b38a3-91fc-5605-94a2-ee2116b3bd83"
authors = ["Bogumił Kamiński <bkamins@sgh.waw.pl>", "William Manning <wmanning@cra.com>"]
authors = [
"Bogumił Kamiński <bkamins@sgh.waw.pl>",
"William Manning <wmanning@cra.com>",
"Mark Baum <markmbaum@protonmail.com>"
]
version = "0.2.0"

[compat]
julia = "^1.0.5"
julia = "^1.0"

[extras]
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["SparseArrays", "Test"]
test = ["Test"]
43 changes: 32 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
ReadOnlyArrays.jl
=============

[![Travis Build Status](https://travis-ci.org/bkamins/ReadOnlyArrays.jl.svg?branch=master)](https://travis-ci.org/bkamins/ReadOnlyArrays.jl)
[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/phgcro59kntb2xtf/branch/master?svg=true)](https://ci.appveyor.com/project/bkamins/readonlyarrays-jl/branch/master)
[![Coverage Status](https://coveralls.io/repos/github/bkamins/ReadOnlyArrays.jl/badge.svg?branch=master)](https://coveralls.io/github/bkamins/ReadOnlyArrays.jl?branch=master)
[![codecov.io](http://codecov.io/github/bkamins/ReadOnlyArrays.jl/coverage.svg?branch=master)](http://codecov.io/github/bkamins/ReadOnlyArrays.jl?branch=master)
This small package provides the `ReadOnlyArray` type, which wraps any `AbstractArray` and reimplements the array inferface without the setindex! function. The array can be used in all the usually ways but its elements cannot be modified. Attempting to set an element's value will raise an error. This functionality can be used to protect arrays that are intended to have unchanged values from unintended changes.

A wrapper `ReadOnlyArray` type around `AbstractArray` that is read-only
A `ReadOnlyArray` is not a `StaticArray` from [`StaticArrays.jl`](https://github.com/JuliaArrays/StaticArrays.jl). Static arrays are statically sized and also usually immutable, but are intended to accelerate common operations on *small* arrays. A `ReadOnlyArray` wraps arrays of any size and does not reimplement any functionality except the usual [array interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array).

For convenience, there are also `ReadOnlyVector` and `ReadOnlyMatrix` aliases available.

### Installation

At the Julia REPL run:
`using Pkg; Pkg.add("ReadOnlyArrays")`.
In the Julia REPL:

```julia
using Pkg
Pkg.add("ReadOnlyArrays")
```

or use package management mode by pressing `]` and entering `add ReadOnlyArrays`.

### Usage

### Documentation
Wrap any array by contructing a read-only version.
```julia
using ReadOnlyArrays

At the Julia REPL execute:
`using ReadOnlyArrays`,
then type `?ReadOnlyArray` and press enter to get help.
x = [1.0, 2.0, 3.0]
x = ReadOnlyArray(x)
```
The elements of this array cannot be modified. Attempting to set element values
```julia
x[1] = 2.0
```
will raise an error
```
ERROR: CanonicalIndexError: setindex! not defined for ReadOnlyVector{Float64, Vector{Float64}}
```
This read only array also identifies as a read only vector, for convenience.
```julia
typeof(y) <: ReadOnlyVector
```
1 change: 0 additions & 1 deletion REQUIRE

This file was deleted.

44 changes: 0 additions & 44 deletions appveyor.yml

This file was deleted.

107 changes: 67 additions & 40 deletions src/ReadOnlyArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@ module ReadOnlyArrays

export ReadOnlyArray, ReadOnlyVector, ReadOnlyMatrix

"""
ReadOnlyArray(a)
using Base: @propagate_inbounds

Return a read-only view into the parent array `a`. Most iteration, indexing,
abstract arrays and strided arrays interface functions defined for array `a`
are transparently defined for `ReadOnlyArray(a)`.
The exceptions are `setindex!` which is not allowed for `ReadOnlyArray`
and `similar` which uses the default definitions for `AbstractArray` from Base.
Also when used in broadcasting `ReadOnlyArray` uses default broadcast machinery.
"""
ReadOnlyArray(X)

Use `parent` function to access the parent array of `ReadOnlyArray`.
Returns a read-only view into the parent array `X`.

# Examples
```jldoctest
Expand All @@ -30,50 +25,82 @@ julia> r[1]
1

julia> r[1] = 10
ERROR: setindex! not defined for ReadOnlyArray{Int64,2,Array{Int64,2}}
CanonicalIndexError: setindex! not defined for ReadOnlyArray{Int64,2,Array{Int64,2}}
[...]
```
"""
struct ReadOnlyArray{T,N,P} <: AbstractArray{T,N}
parent::P
ReadOnlyArray(parent::AbstractArray{T,N}) where{T,N} =
struct ReadOnlyArray{T,N,A} <: AbstractArray{T,N}
parent::A
function ReadOnlyArray(parent::AbstractArray{T,N}) where {T,N}
new{T,N,typeof(parent)}(parent)
end
end
ReadOnlyArray{T}(parent::AbstractArray{T,N}) where{T,N} = ReadOnlyArray(parent)

ReadOnlyArray{T}(parent::AbstractArray{T,N}) where {T,N} = ReadOnlyArray(parent)

ReadOnlyArray{T,N}(parent::AbstractArray{T,N}) where {T,N} = ReadOnlyArray(parent)
ReadOnlyArray{T,N,P}(parent::P) where {T, N, P<:AbstractArray{T,N}} = ReadOnlyArray(parent)

Base.IteratorSize(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} =
ReadOnlyArray{T,N,P}(parent::P) where {T,N,P<:AbstractArray{T,N}} = ReadOnlyArray(parent)

#--------------------------------------
# aliases

const ReadOnlyVector{T,P} = ReadOnlyArray{T,1,P}

ReadOnlyVector(parent::AbstractVector) = ReadOnlyArray(parent)

const ReadOnlyMatrix{T,P} = ReadOnlyArray{T,2,P}

ReadOnlyMatrix(parent::AbstractMatrix) = ReadOnlyArray(parent)

#--------------------------------------
# interface, excluding setindex!() and similar()
# https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-parentay

Base.size(x::ReadOnlyArray, args...) = size(x.parent, args...)

@propagate_inbounds function Base.getindex(x::ReadOnlyArray, args...)
getindex(x.parent, args...)
end

Base.IndexStyle(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} = IndexStyle(P)

Base.iterate(x::ReadOnlyArray, args...) = iterate(x.parent, args...)

Base.length(x::ReadOnlyArray) = length(x.parent)

Base.similar(x::ReadOnlyArray) = similar(x.parent) |> ReadOnlyArray

Base.axes(x::ReadOnlyArray) = axes(x.parent)

function Base.IteratorSize(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P}
Base.IteratorSize(P)
Base.IteratorEltype(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} =
end

function Base.IteratorEltype(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P}
Base.IteratorEltype(P)
Base.eltype(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} =
end

function Base.eltype(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P}
eltype(P)
Base.size(roa::ReadOnlyArray, args...) = size(roa.parent, args...)
Base.@propagate_inbounds Base.getindex(roa::ReadOnlyArray, I...) =
getindex(roa.parent, I...)
Base.firstindex(roa::ReadOnlyArray) = firstindex(roa.parent)
Base.lastindex(roa::ReadOnlyArray) = lastindex(roa.parent)
Base.IndexStyle(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} = IndexStyle(P)
Base.iterate(roa::ReadOnlyArray, args...) = iterate(roa.parent, args...)
Base.length(roa::ReadOnlyArray) = length(roa.parent)
end

Base.axes(roa::ReadOnlyArray) = axes(roa.parent)
Base.strides(roa::ReadOnlyArray) = strides(roa.parent)
Base.unsafe_convert(p::Type{Ptr{T}}, roa::ReadOnlyArray) where {T} =
Base.unsafe_convert(p, roa.parent)
Base.stride(roa::ReadOnlyArray, i::Int) = stride(roa.parent, i)
Base.parent(roa::ReadOnlyArray) = roa.parent
Base.firstindex(x::ReadOnlyArray) = firstindex(x.parent)

Base.convert(::Type{ReadOnlyArray{T,N}}, mutable_arr::AbstractArray{T,N}) where {T,N} = ReadOnlyArray(mutable_arr)
Base.lastindex(x::ReadOnlyArray) = lastindex(x.parent)

# Define aliases:
const ReadOnlyVector{T, P} = ReadOnlyArray{T,1,P}
const ReadOnlyMatrix{T,P} = ReadOnlyArray{T,2,P}
Base.strides(x::ReadOnlyArray) = strides(x.parent)

# Allow construction through the alias:
ReadOnlyVector(parent::AbstractVector) = ReadOnlyArray(parent)
ReadOnlyMatrix(parent::AbstractMatrix) = ReadOnlyArray(parent)
function Base.unsafe_convert(p::Type{Ptr{T}}, x::ReadOnlyArray) where {T}
Base.unsafe_convert(p, x.parent)
end

Base.stride(x::ReadOnlyArray, i::Int) = stride(x.parent, i)

end # module
Base.parent(x::ReadOnlyArray) = x.parent

function Base.convert(::Type{ReadOnlyArray{T,N}}, mutable_parent::AbstractArray{T,N}) where {T,N}
ReadOnlyArray(mutable_parent)
end

end
Loading