cz_system_info 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +18 -0
- data/.gitignore +8 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/cz_system_info.gemspec +36 -0
- data/lib/cz_system_info/cpu.rb +167 -0
- data/lib/cz_system_info/filesystem/constants.rb +72 -0
- data/lib/cz_system_info/filesystem/functions.rb +75 -0
- data/lib/cz_system_info/filesystem/structs.rb +216 -0
- data/lib/cz_system_info/filesystem.rb +450 -0
- data/lib/cz_system_info/memory.rb +66 -0
- data/lib/cz_system_info/uptime.rb +222 -0
- data/lib/cz_system_info/version.rb +5 -0
- data/lib/cz_system_info.rb +12 -0
- metadata +78 -0
| @@ -0,0 +1,66 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # The CzSystemInfo module serves as a namespace only.
         | 
| 4 | 
            +
            module CzSystemInfo
         | 
| 5 | 
            +
              # The Memory module provides various functions that return information
         | 
| 6 | 
            +
              # regarding the memory on your system.
         | 
| 7 | 
            +
              module Memory
         | 
| 8 | 
            +
                MEMORY_FILE = '/proc/meminfo'
         | 
| 9 | 
            +
                MEMINFO_REGEX = /(.*)?:\s+?(\d+)/.freeze
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                private_constant :MEMORY_FILE
         | 
| 12 | 
            +
                private_constant :MEMINFO_REGEX
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Obtain detailed memory information about your host in the form of a hash.
         | 
| 15 | 
            +
                # Note that the exact nature of this hash is largely dependent on your
         | 
| 16 | 
            +
                # operating system.
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                def memory
         | 
| 19 | 
            +
                  hash = {}
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  File.foreach(MEMORY_FILE) do |line|
         | 
| 22 | 
            +
                    key, value = MEMINFO_REGEX.match(line.chomp).captures
         | 
| 23 | 
            +
                    hash[key] = value.to_i
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  hash
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                # Total memory in bytes. By default this is only physical memory, but
         | 
| 30 | 
            +
                # if the +extended+ option is set to true, then swap memory is included
         | 
| 31 | 
            +
                # as part of the total.
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                def total(extended: false)
         | 
| 34 | 
            +
                  hash = memory
         | 
| 35 | 
            +
                  extended ? (hash['MemTotal'] + hash['SwapTotal']) * 1024 : hash['MemTotal'] * 1024
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # The memory currently available, in bytes. By default this is only
         | 
| 39 | 
            +
                # physical memory, but if the +extended+ option is set to true, then free
         | 
| 40 | 
            +
                # swap memory is also included.
         | 
| 41 | 
            +
                #
         | 
| 42 | 
            +
                def free(extended: false)
         | 
| 43 | 
            +
                  hash = memory
         | 
| 44 | 
            +
                  extended ? (hash['MemFree'] + hash['SwapFree']) * 1024 : hash['MemFree'] * 1024
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # The memory, in bytes, currently in use. By default this is only
         | 
| 48 | 
            +
                # physical memory, but if the +extended+ option is set to true then
         | 
| 49 | 
            +
                # swap is included in the calculation.
         | 
| 50 | 
            +
                #
         | 
| 51 | 
            +
                def used(extended: false)
         | 
| 52 | 
            +
                  hash = memory
         | 
| 53 | 
            +
                  (total(extended: extended) - free(extended: extended) - hash['Buffers'] - hash['Cached'] - hash['Slab']) * 1024
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # A number between 0 and 100 that specifies the approximate percentage of
         | 
| 57 | 
            +
                # memory that is in use. If the +extended+ option is set to true then
         | 
| 58 | 
            +
                # swap memory is included in the calculation.
         | 
| 59 | 
            +
                #
         | 
| 60 | 
            +
                def load(extended: false)
         | 
| 61 | 
            +
                  (used(extended: extended) / total(extended: extended).to_f).round(2) * 100
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                module_function :memory, :total, :free, :used, :load
         | 
| 65 | 
            +
              end # Memory
         | 
| 66 | 
            +
            end # CzSystemInfo
         | 
| @@ -0,0 +1,222 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'ffi'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # The CzSystemInfo module serves as a namespace only.
         | 
| 6 | 
            +
            module CzSystemInfo
         | 
| 7 | 
            +
              # The Uptime class encapsulates various bits of information regarding your
         | 
| 8 | 
            +
              # system's uptime, including boot time.
         | 
| 9 | 
            +
              class Uptime
         | 
| 10 | 
            +
                extend FFI::Library
         | 
| 11 | 
            +
                ffi_lib FFI::Library::LIBC
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # Error typically raised in one of the Uptime methods should fail.
         | 
| 14 | 
            +
                class Error < StandardError; end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                # Hit this issue on Linux, not sure why
         | 
| 17 | 
            +
                begin
         | 
| 18 | 
            +
                  find_type(:clock_t)
         | 
| 19 | 
            +
                rescue TypeError
         | 
| 20 | 
            +
                  typedef(:long, :clock_t)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                attach_function :strerror, [:int],     :string
         | 
| 24 | 
            +
                attach_function :sysconf,  [:int],     :long
         | 
| 25 | 
            +
                attach_function :time,     [:pointer], :time_t
         | 
| 26 | 
            +
                attach_function :times,    [:pointer], :clock_t
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                private_class_method :strerror, :sysconf, :time, :times, :new
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                begin
         | 
| 31 | 
            +
                  attach_function :sysctl, %i[pointer uint pointer pointer pointer size_t], :int
         | 
| 32 | 
            +
                  private_class_method :sysctl
         | 
| 33 | 
            +
                rescue FFI::NotFoundError
         | 
| 34 | 
            +
                  attach_function :setutxent, [], :void
         | 
| 35 | 
            +
                  attach_function :getutxent, [], :pointer
         | 
| 36 | 
            +
                  attach_function :endutxent, [], :void
         | 
| 37 | 
            +
                  private_class_method :setutxent, :getutxent, :endutxent
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                CTL_KERN      = 1   # Kernel
         | 
| 41 | 
            +
                KERN_BOOTTIME = 21  # Time kernel was booted
         | 
| 42 | 
            +
                TICKS         = 100 # Ticks per second (TODO: use sysconf)
         | 
| 43 | 
            +
                BOOT_TIME     = 2   # Boot time
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                private_constant :CTL_KERN
         | 
| 46 | 
            +
                private_constant :KERN_BOOTTIME
         | 
| 47 | 
            +
                private_constant :TICKS
         | 
| 48 | 
            +
                private_constant :BOOT_TIME
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                class Tms < FFI::Struct
         | 
| 51 | 
            +
                  layout(
         | 
| 52 | 
            +
                    :tms_utime, :clock_t,
         | 
| 53 | 
            +
                    :tms_stime, :clock_t,
         | 
| 54 | 
            +
                    :tms_cutime, :clock_t,
         | 
| 55 | 
            +
                    :tms_cstime, :clock_t
         | 
| 56 | 
            +
                  )
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                private_constant :Tms
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                class Timeval < FFI::Struct
         | 
| 62 | 
            +
                  layout(
         | 
| 63 | 
            +
                    :tv_sec,  :long,
         | 
| 64 | 
            +
                    :tv_usec, :long
         | 
| 65 | 
            +
                  )
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                private_constant :Timeval
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                class ExitStatus < FFI::Struct
         | 
| 71 | 
            +
                  layout(
         | 
| 72 | 
            +
                    :e_termination, :short,
         | 
| 73 | 
            +
                    :e_exit, :short
         | 
| 74 | 
            +
                  )
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                private_constant :ExitStatus
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                class Utmpx < FFI::Struct
         | 
| 80 | 
            +
                  layout(
         | 
| 81 | 
            +
                    :ut_user, [:char, 32],
         | 
| 82 | 
            +
                    :ut_id,   [:char, 4],
         | 
| 83 | 
            +
                    :ut_line, [:char, 32],
         | 
| 84 | 
            +
                    :ut_pid,  :pid_t,
         | 
| 85 | 
            +
                    :ut_type, :short,
         | 
| 86 | 
            +
                    :ut_exit, ExitStatus,
         | 
| 87 | 
            +
                    :ut_tv,   Timeval,
         | 
| 88 | 
            +
                    :ut_session, :int,
         | 
| 89 | 
            +
                    :padding, [:int, 5],
         | 
| 90 | 
            +
                    :ut_host, [:char, 257]
         | 
| 91 | 
            +
                  )
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                private_constant :Utmpx
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                # Returns a Time object indicating the time the system was last booted.
         | 
| 97 | 
            +
                #
         | 
| 98 | 
            +
                # Example:
         | 
| 99 | 
            +
                #
         | 
| 100 | 
            +
                #    CzSystemInfo::Uptime.boot_time # => Mon Jul 13 06:08:25 -0600 2009
         | 
| 101 | 
            +
                #
         | 
| 102 | 
            +
                def self.boot_time
         | 
| 103 | 
            +
                  if RbConfig::CONFIG['host_os'] =~ /linux/i
         | 
| 104 | 
            +
                    Time.now - seconds
         | 
| 105 | 
            +
                  elsif respond_to?(:sysctl, true)
         | 
| 106 | 
            +
                    tv = Timeval.new
         | 
| 107 | 
            +
                    mib  = FFI::MemoryPointer.new(:int, 2).write_array_of_int([CTL_KERN, KERN_BOOTTIME])
         | 
| 108 | 
            +
                    size = FFI::MemoryPointer.new(:long, 1).write_int(tv.size)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    if sysctl(mib, 2, tv, size, nil, 0) != 0
         | 
| 111 | 
            +
                      raise SystemCallError, "sysctl function failed: #{strerror(FFI.errno)}"
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    Time.at(tv[:tv_sec], tv[:tv_usec])
         | 
| 115 | 
            +
                  else
         | 
| 116 | 
            +
                    begin
         | 
| 117 | 
            +
                      setutxent()
         | 
| 118 | 
            +
                      while ent = Utmpx.new(getutxent())
         | 
| 119 | 
            +
                        if ent[:ut_type] == BOOT_TIME
         | 
| 120 | 
            +
                          time = Time.at(ent[:ut_tv][:tv_sec], ent[:ut_tv][:tv_usec])
         | 
| 121 | 
            +
                          break
         | 
| 122 | 
            +
                        end
         | 
| 123 | 
            +
                      end
         | 
| 124 | 
            +
                    ensure
         | 
| 125 | 
            +
                      endutxent()
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
                    time
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                # Returns the total number of seconds of uptime.
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                # Example:
         | 
| 134 | 
            +
                #
         | 
| 135 | 
            +
                #    CzSystemInfo::Uptime.seconds => 118800
         | 
| 136 | 
            +
                #
         | 
| 137 | 
            +
                def self.seconds
         | 
| 138 | 
            +
                  if RbConfig::CONFIG['host_os'] =~ /linux/i
         | 
| 139 | 
            +
                    # rubocop:disable Lint/RescueException
         | 
| 140 | 
            +
                    begin
         | 
| 141 | 
            +
                      File.read('/proc/uptime').split.first.to_i
         | 
| 142 | 
            +
                    rescue Exception => err
         | 
| 143 | 
            +
                      raise Error, err
         | 
| 144 | 
            +
                    end
         | 
| 145 | 
            +
                    # rubocop:enable Lint/RescueException
         | 
| 146 | 
            +
                  elsif respond_to?(:sysctl, true)
         | 
| 147 | 
            +
                    tv   = Timeval.new
         | 
| 148 | 
            +
                    mib  = FFI::MemoryPointer.new(:int, 2).write_array_of_int([CTL_KERN, KERN_BOOTTIME])
         | 
| 149 | 
            +
                    size = FFI::MemoryPointer.new(:long, 1).write_int(tv.size)
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                    if sysctl(mib, 2, tv, size, nil, 0) != 0
         | 
| 152 | 
            +
                      raise SystemCallError, "sysctl function failed: #{strerror(FFI.errno)}"
         | 
| 153 | 
            +
                    end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                    time(nil) - tv[:tv_sec]
         | 
| 156 | 
            +
                  else
         | 
| 157 | 
            +
                    tms = Tms.new
         | 
| 158 | 
            +
                    times(tms) / TICKS
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
                end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                # Returns the total number of minutes of uptime.
         | 
| 163 | 
            +
                #
         | 
| 164 | 
            +
                # Example:
         | 
| 165 | 
            +
                #
         | 
| 166 | 
            +
                #    CzSystemInfo::Uptime.minutes # => 678
         | 
| 167 | 
            +
                #
         | 
| 168 | 
            +
                def self.minutes
         | 
| 169 | 
            +
                  seconds / 60
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                # Returns the total number of hours of uptime.
         | 
| 173 | 
            +
                #
         | 
| 174 | 
            +
                # Example:
         | 
| 175 | 
            +
                #
         | 
| 176 | 
            +
                #    CzSystemInfo::Uptime.hours # => 31
         | 
| 177 | 
            +
                #
         | 
| 178 | 
            +
                def self.hours
         | 
| 179 | 
            +
                  seconds / 3600
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                # Returns the total number of days of uptime.
         | 
| 183 | 
            +
                #
         | 
| 184 | 
            +
                # Example:
         | 
| 185 | 
            +
                #
         | 
| 186 | 
            +
                #    CzSystemInfo::Uptime.days # => 2
         | 
| 187 | 
            +
                #
         | 
| 188 | 
            +
                def self.days
         | 
| 189 | 
            +
                  seconds / 86400
         | 
| 190 | 
            +
                end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                # Returns the uptime as a colon separated string, including days,
         | 
| 193 | 
            +
                # hours, minutes and seconds.
         | 
| 194 | 
            +
                #
         | 
| 195 | 
            +
                # Example:
         | 
| 196 | 
            +
                #
         | 
| 197 | 
            +
                #    CzSystemInfo::Uptime.uptime # => "1:9:24:57"
         | 
| 198 | 
            +
                #
         | 
| 199 | 
            +
                def self.uptime
         | 
| 200 | 
            +
                  secs  = seconds
         | 
| 201 | 
            +
                  days  = secs / 86400
         | 
| 202 | 
            +
                  secs -= days * 86400
         | 
| 203 | 
            +
                  hours = secs / 3600
         | 
| 204 | 
            +
                  secs -= hours * 3600
         | 
| 205 | 
            +
                  mins = secs / 60
         | 
| 206 | 
            +
                  secs -= mins * 60
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                  "#{days}:#{hours}:#{mins}:#{secs}"
         | 
| 209 | 
            +
                end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                # Returns the uptime as a four element array, including days, hours,
         | 
| 212 | 
            +
                # minutes and seconds.
         | 
| 213 | 
            +
                #
         | 
| 214 | 
            +
                # Example:
         | 
| 215 | 
            +
                #
         | 
| 216 | 
            +
                #    CzSystemInfo::Uptime.dhms # => [1,9,24,57]
         | 
| 217 | 
            +
                #
         | 
| 218 | 
            +
                def self.dhms
         | 
| 219 | 
            +
                  uptime.split(':')
         | 
| 220 | 
            +
                end
         | 
| 221 | 
            +
              end
         | 
| 222 | 
            +
            end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative "cz_system_info/version"
         | 
| 4 | 
            +
            require_relative "cz_system_info/cpu"
         | 
| 5 | 
            +
            require_relative "cz_system_info/filesystem"
         | 
| 6 | 
            +
            require_relative "cz_system_info/memory"
         | 
| 7 | 
            +
            require_relative "cz_system_info/uptime"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module CzSystemInfo
         | 
| 10 | 
            +
              class Error < StandardError; end
         | 
| 11 | 
            +
              # Your code goes here...
         | 
| 12 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: cz_system_info
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - hayate
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: exe
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2022-10-28 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: ffi
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '1.1'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.1'
         | 
| 27 | 
            +
            description: Move Daniel Berger's sys code into one.
         | 
| 28 | 
            +
            email:
         | 
| 29 | 
            +
            - holdstock@yeah.net
         | 
| 30 | 
            +
            executables: []
         | 
| 31 | 
            +
            extensions: []
         | 
| 32 | 
            +
            extra_rdoc_files: []
         | 
| 33 | 
            +
            files:
         | 
| 34 | 
            +
            - ".github/workflows/main.yml"
         | 
| 35 | 
            +
            - ".gitignore"
         | 
| 36 | 
            +
            - Gemfile
         | 
| 37 | 
            +
            - LICENSE.txt
         | 
| 38 | 
            +
            - README.md
         | 
| 39 | 
            +
            - Rakefile
         | 
| 40 | 
            +
            - bin/console
         | 
| 41 | 
            +
            - bin/setup
         | 
| 42 | 
            +
            - cz_system_info.gemspec
         | 
| 43 | 
            +
            - lib/cz_system_info.rb
         | 
| 44 | 
            +
            - lib/cz_system_info/cpu.rb
         | 
| 45 | 
            +
            - lib/cz_system_info/filesystem.rb
         | 
| 46 | 
            +
            - lib/cz_system_info/filesystem/constants.rb
         | 
| 47 | 
            +
            - lib/cz_system_info/filesystem/functions.rb
         | 
| 48 | 
            +
            - lib/cz_system_info/filesystem/structs.rb
         | 
| 49 | 
            +
            - lib/cz_system_info/memory.rb
         | 
| 50 | 
            +
            - lib/cz_system_info/uptime.rb
         | 
| 51 | 
            +
            - lib/cz_system_info/version.rb
         | 
| 52 | 
            +
            homepage: https://github.com/hinagiku/cz_system_info
         | 
| 53 | 
            +
            licenses:
         | 
| 54 | 
            +
            - MIT
         | 
| 55 | 
            +
            metadata:
         | 
| 56 | 
            +
              homepage_uri: https://github.com/hinagiku/cz_system_info
         | 
| 57 | 
            +
              source_code_uri: https://github.com/hinagiku/cz_system_info
         | 
| 58 | 
            +
              changelog_uri: https://github.com/hinagiku/cz_system_info
         | 
| 59 | 
            +
            post_install_message: 
         | 
| 60 | 
            +
            rdoc_options: []
         | 
| 61 | 
            +
            require_paths:
         | 
| 62 | 
            +
            - lib
         | 
| 63 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 64 | 
            +
              requirements:
         | 
| 65 | 
            +
              - - ">="
         | 
| 66 | 
            +
                - !ruby/object:Gem::Version
         | 
| 67 | 
            +
                  version: 2.3.0
         | 
| 68 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 69 | 
            +
              requirements:
         | 
| 70 | 
            +
              - - ">="
         | 
| 71 | 
            +
                - !ruby/object:Gem::Version
         | 
| 72 | 
            +
                  version: '0'
         | 
| 73 | 
            +
            requirements: []
         | 
| 74 | 
            +
            rubygems_version: 3.2.3
         | 
| 75 | 
            +
            signing_key: 
         | 
| 76 | 
            +
            specification_version: 4
         | 
| 77 | 
            +
            summary: Move Daniel Berger's sys code into one.
         | 
| 78 | 
            +
            test_files: []
         |