From a9fb8b4e45a4451871670fda624d3e3ab1704af2 Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Thu, 30 Sep 2021 18:45:27 -0500 Subject: [PATCH 1/3] Improve pretty-printing to support invalid bitflags This may occur when values are reinterpreted from raw integers. Rather than printing a chain of ORs which do not sum to the explicit value (or worse yet, print nothing for a disjoint bitset), just tack on to the end of the chain the explicit numerical value of all unhandled bits. We can even represent this in the non-compact case as a reinterpret expression which is copy-pastable to re-form the given value. --- src/BitFlags.jl | 29 +++++++++++++++++++++++----- test/runtests.jl | 50 +++++++++++++++++++++++++++++------------------- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/BitFlags.jl b/src/BitFlags.jl index ba2186a..cfc606d 100644 --- a/src/BitFlags.jl +++ b/src/BitFlags.jl @@ -26,15 +26,28 @@ Base.:&(x::T, y::T) where {T<:BitFlag} = T(Integer(x) & Integer(y)) function Base.print(io::IO, x::T) where T<:BitFlag compact = get(io, :compact, false)::Bool xi = Integer(x) + + function _printnum(v) + if compact + show(io, v) + else + print(io, "reinterpret(") + show(IOContext(io, :compact => false), T) + print(io, ", ") + show(io, v) + print(io, ")") + end + end + # abnormal case where bitflag is all unset but 0 not permitted + if !haszero(T) && iszero(xi) + _printnum(xi) + return + end multi = (haszero(T) ? !iszero(xi) : true) && !compact && !ispow2(xi) first = true sep = compact ? "|" : " | " for (i, sym) in Iterators.reverse(namemap(T)) - if haszero(T) && iszero(i) && iszero(xi) - print(io, sym) - break - end - if !iszero(i & xi) + if (first && iszero(i) && iszero(xi)) || !iszero(xi & i) if first multi && print(io, "(") first = false @@ -42,8 +55,14 @@ function Base.print(io::IO, x::T) where T<:BitFlag print(io, sep) end print(io, sym) + xi ⊻= i end end + # abnormal case where set bits are not part of nominal set + if !iszero(xi) + !first && print(io, sep) + _printnum(xi) + end multi && print(io, ")") nothing end diff --git a/test/runtests.jl b/test/runtests.jl index 7519731..260092a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -182,27 +182,37 @@ end @test repr(SubModule.BIT_ONE | SubModule.BIT_EIGHT) == "(BIT_EIGHT | BIT_ONE)::Main.SubModule.Bits = 0x09" @test repr(NONE | READ) == "READ::FilePerms = 0x04" - let io = IOBuffer(), ioc = IOContext(io, :compact => true, :module => Main) - show(io, MIME"text/plain"(), BitFlag) - @test String(take!(io)) == "BitFlag" - show(ioc, MIME"text/plain"(), BitFlag) - @test String(take!(io)) == "BitFlag" - - # Explicit :compact => false required for consistency across Julia versions + let io = IOBuffer(), + ioc = IOContext(io, :compact => true, :module => Main), iof = IOContext(io, :compact => false, :module => Main) - show(iof, MIME"text/plain"(), Union{FilePerms, SubModule.Bits}) - @test String(take!(io)) == "Union{FilePerms, Main.SubModule.Bits}" - show(ioc, MIME"text/plain"(), Union{FilePerms, SubModule.Bits}) - @test String(take!(io)) == "Union{FilePerms, Bits}" - - show(ioc, NONE) - @test String(take!(io)) == "NONE" - show(ioc, SubModule.BIT_ONE) - @test String(take!(io)) == "BIT_ONE" - show(ioc, EXEC | READ) - @test String(take!(io)) == "READ|EXEC" - show(ioc, SubModule.BIT_ONE | SubModule.BIT_EIGHT) - @test String(take!(io)) == "BIT_EIGHT|BIT_ONE" + # Explicit :compact => false required for consistency across Julia versions + + stringf(x) = (show(iof, MIME"text/plain"(), x); String(take!(io))) + stringc(x) = (show(ioc, MIME"text/plain"(), x); String(take!(io))) + + @test stringf(BitFlag) == "BitFlag" + @test stringc(BitFlag) == "BitFlag" + + @test stringf(Union{FilePerms, SubModule.Bits}) == "Union{FilePerms, Main.SubModule.Bits}" + @test stringc(Union{FilePerms, SubModule.Bits}) == "Union{FilePerms, Bits}" + + @test stringc(NONE) == "NONE" + @test stringc(SubModule.BIT_ONE) == "BIT_ONE" + @test stringc(EXEC | READ) == "READ|EXEC" + @test stringc(SubModule.BIT_ONE | SubModule.BIT_EIGHT) == "BIT_EIGHT|BIT_ONE" + + # Handle exceptional cases where set bits are not in the allowed set + @test stringf(reinterpret(SubModule.Bits, 0x00)) == "reinterpret(Main.SubModule.Bits, 0x00)::Main.SubModule.Bits = 0x00" + @test stringc(reinterpret(SubModule.Bits, 0x00)) == "0x00" + + @test stringf(reinterpret(SubModule.Bits, 0x11)) == "(BIT_ONE | reinterpret(Main.SubModule.Bits, 0x10))::Main.SubModule.Bits = 0x11" + @test stringc(reinterpret(SubModule.Bits, 0x11)) == "BIT_ONE|0x10" + + @test stringf(reinterpret(FilePerms, 0x08)) == "reinterpret(FilePerms, 0x08)::FilePerms = 0x08" + @test stringc(reinterpret(FilePerms, 0x08)) == "0x08" + + @test stringf(reinterpret(FilePerms, 0xff)) == "(READ | WRITE | EXEC | reinterpret(FilePerms, 0xf8))::FilePerms = 0xff" + @test stringc(reinterpret(FilePerms, 0xff)) == "READ|WRITE|EXEC|0xf8" end #end From e7ffa9597b9354faef83a508c46d5589e3822bf3 Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Thu, 30 Sep 2021 18:51:17 -0500 Subject: [PATCH 2/3] Update workflow configurations --- .github/workflows/CompatHelper.yml | 20 +++++++++++++++----- .github/workflows/RegisterAction.yml | 14 ++++++++++++++ .github/workflows/ci.yml | 19 +++++++++++++++---- 3 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/RegisterAction.yml diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml index cba9134..1a5cd34 100644 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -1,16 +1,26 @@ name: CompatHelper on: schedule: - - cron: 0 0 * * * + - cron: 48 16 * * * workflow_dispatch: jobs: CompatHelper: runs-on: ubuntu-latest steps: - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() + - name: "Install CompatHelper" + run: | + import Pkg + name = "CompatHelper" + uuid = "aa819f21-2bde-4658-8897-bab36330d9b7" + version = "2" + Pkg.add(; name, uuid, version) + shell: julia --color=yes {0} + - name: "Run CompatHelper" + run: | + import CompatHelper + CompatHelper.main() + shell: julia --color=yes {0} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} - run: julia -e 'using CompatHelper; CompatHelper.main()' + # COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }} diff --git a/.github/workflows/RegisterAction.yml b/.github/workflows/RegisterAction.yml new file mode 100644 index 0000000..1771e31 --- /dev/null +++ b/.github/workflows/RegisterAction.yml @@ -0,0 +1,14 @@ +name: RegisterAction +on: + workflow_dispatch: + inputs: + version: + description: Version to register or component to bump + required: true +jobs: + register: + runs-on: ubuntu-latest + steps: + - uses: julia-actions/RegisterAction@latest + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8441489..5021d4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,17 +1,28 @@ name: CI on: - - push - - pull_request + push: + branches: + - 'master' + tags: '*' + paths-ignore: + - 'README.md' + - '.github/workflows/**' + pull_request: + paths-ignore: + - 'README.md' + - '.github/workflows/**' + jobs: test: - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + if: "!contains(github.event.head_commit.message, 'skip ci')" + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: version: - '1.0' # earliest supported - - '1.5' # latest release + - '1' # latest release - 'nightly' os: - ubuntu-latest From 51eb396a0f7b06e36f3cd261cf87291e7f0ab58c Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Thu, 30 Sep 2021 19:13:59 -0500 Subject: [PATCH 3/3] Bump version for another release --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 56d7fe4..9c11634 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "BitFlags" uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" -authors = ["Justin Willmert "] -version = "0.1.3" +authors = ["Justin Willmert "] +version = "0.1.4" [compat] julia = "1"