New upstream version 3.9.3+dfsg

parent a19a6c2a
# frozen_string_literal: true
require 'addressable/uri'
require 'addressable/template'
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
begin
require "addressable/idna/native"
rescue LoadError
# libidn or the idn gem was not available, fall back on a pure-Ruby
# implementation...
require "addressable/idna/pure"
end
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
require "idn"
module Addressable
module IDNA
def self.punycode_encode(value)
IDN::Punycode.encode(value.to_s)
end
def self.punycode_decode(value)
IDN::Punycode.decode(value.to_s)
end
def self.unicode_normalize_kc(value)
IDN::Stringprep.nfkc_normalize(value.to_s)
end
def self.to_ascii(value)
value.to_s.split('.', -1).map do |segment|
if segment.size > 0 && segment.size < 64
IDN::Idna.toASCII(segment, IDN::Idna::ALLOW_UNASSIGNED)
elsif segment.size >= 64
segment
else
''
end
end.join('.')
end
def self.to_unicode(value)
value.to_s.split('.', -1).map do |segment|
if segment.size > 0 && segment.size < 64
IDN::Idna.toUnicode(segment, IDN::Idna::ALLOW_UNASSIGNED)
elsif segment.size >= 64
segment
else
''
end
end.join('.')
end
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
# Used to prevent the class/module from being loaded more than once
if !defined?(Addressable::VERSION)
module Addressable
module VERSION
MAJOR = 2
MINOR = 6
TINY = 0
STRING = [MAJOR, MINOR, TINY].join('.')
end
end
end
# -*- coding: utf-8 -*-
require "delayer/version"
require "delayer/error"
require "delayer/extend"
require "delayer/procedure"
require "monitor"
module Delayer
class << self
attr_accessor :default
# Generate new Delayer class.
# ==== Args
# [options]
# Hash
# expire :: processing expire (secs, 0=unlimited)
# priority :: priorities
# default :: default priotity
# ==== Return
# A new class
def generate_class(options = {})
Class.new do
include ::Delayer
@expire = options[:expire] || 0
if options.has_key?(:priority)
@priorities = options[:priority]
@default_priority = options[:default]
else
@priorities = [:normal]
@default_priority = :normal
end
end
end
def method_missing(*args, &proc)
(@default ||= generate_class).__send__(*args, &proc)
end
end
end
# coding: utf-8
require "delayer"
require "delayer/deferred/deferred"
require "delayer/deferred/deferredable"
require "delayer/deferred/enumerable"
require "delayer/deferred/enumerator"
require "delayer/deferred/thread"
require "delayer/deferred/tools"
require "delayer/deferred/version"
module Delayer
module Deferred
class << self
#真ならデバッグ情報を集める
attr_accessor :debug
def new(*rest, name: caller_locations(1,1).first.to_s, &block)
super(*rest, name: name, &block)
end
def method_missing(*rest, &block)
Delayer::Deferred::Promise.__send__(*rest, &block)
end
def respond_to_missing?(symbol, include_private)
Delayer::Deferred::Promise.respond_to?(symbol, include_private)
end
end
end
module Extend
def Promise
@promise ||= begin
the_delayer = self
Class.new(::Delayer::Deferred::Promise) {
define_singleton_method(:delayer) {
the_delayer } } end
end
alias :Deferred :Promise
#deprecate :Deferred, "Promise", 2018, 03
end
end
Delayer::Deferred.debug = false
# -*- coding: utf-8 -*-
module Delayer::Deferred
module Chain; end
end
require "delayer/deferred/chain/await"
require "delayer/deferred/chain/base"
require "delayer/deferred/chain/next"
require "delayer/deferred/chain/trap"
# -*- coding: utf-8 -*-
require "delayer/deferred/chain/base"
module Delayer::Deferred::Chain
class Await < Base
def initialize(worker:, deferred:)
super()
@worker, @awaiting_deferred = worker, deferred
deferred.add_awaited(self)
end
def activate(response)
change_sequence(:activate)
@worker.give_response(response, @awaiting_deferred)
# TODO: 即座にspoilさせてよさそう
ensure
change_sequence(:complete)
end
def graph_child(output:)
output << graph_mynode
if has_child?
@child.graph_child(output: output)
@awaiting_deferred.graph_child(output: output)
output << "#{__id__} -> #{@child.__id__}"
end
nil
end
def node_name
"Await"
end
def graph_shape
'circle'.freeze
end
def graph_mynode
label = "#{node_name}\n(#{sequence.name})"
"#{__id__} [shape=#{graph_shape},label=#{label.inspect}]"
end
end
end
# -*- coding: utf-8 -*-
require "delayer/deferred/deferredable/chainable"
require "delayer/deferred/deferredable/node_sequence"
module Delayer::Deferred::Chain
class Base
include Delayer::Deferred::Deferredable::NodeSequence
include Delayer::Deferred::Deferredable::Chainable
def initialize(&proc)
fail Error, "Delayer::Deferred::Chain can't create instance." if self.class == Delayer::Deferred::Chain::Base
@proc = proc
end
def activate(response)
change_sequence(:activate)
if evaluate?(response)
@proc.(response.value)
else
response
end
ensure
change_sequence(:complete)
end
def inspect
"#<#{self.class} seq:#{sequence.name} child:#{has_child?}>"
end
def node_name
@proc.source_location.join(':'.freeze)
end
end
end
# -*- coding: utf-8 -*-
require "delayer/deferred/chain/base"
module Delayer::Deferred::Chain
class Next < Base
def evaluate?(response)
response.ok?
end
private
def graph_shape
'box'.freeze
end
end
end
# -*- coding: utf-8 -*-
require "delayer/deferred/chain/base"
module Delayer::Deferred::Chain
class Trap < Base
def evaluate?(response)
response.ng?
end
private
def graph_shape
'diamond'.freeze
end
end
end
# -*- coding: utf-8 -*-
require "delayer/deferred/promise"
require "delayer/deferred/chain"
require "delayer/deferred/deferredable"
require "delayer/deferred/worker"
require "delayer/deferred/version"
module Delayer::Deferred
Deferred = Promise
end
# -*- coding: utf-8 -*-
require "delayer/deferred/version"
module Delayer::Deferred
module Deferredable; end
end
require "delayer/deferred/deferredable/awaitable"
require "delayer/deferred/deferredable/chainable"
require "delayer/deferred/deferredable/graph"
require "delayer/deferred/deferredable/node_sequence"
require "delayer/deferred/deferredable/trigger"
# -*- coding: utf-8 -*-
module Delayer::Deferred::Deferredable
module Awaitable
# _self_ が終了して結果が出るまで呼び出し側のDeferredを停止し、 _self_ の結果を返す。
# 呼び出し側はDeferredブロック内でなければならないが、 _Deferred#next_ を使わずに
# 直接戻り値を得ることが出来る。
# _self_ が失敗した場合は、呼び出し側のDeferredの直近の _trap_ ブロックが呼ばれる。
def +@
response = Fiber.yield(Delayer::Deferred::Request::Await.new(self))
if response.ok?
response.value
else
Delayer::Deferred.fail(response.value)
end
end
def enter_await
change_sequence(:await)
end
def exit_await
change_sequence(:resume)
end
end
end
# -*- coding: utf-8 -*-
require "delayer/deferred/deferredable/awaitable"
require "delayer/deferred/deferredable/graph"
require "delayer/deferred/deferredable/node_sequence"
module Delayer::Deferred::Deferredable
module Chainable
include Awaitable
include Graph
include NodeSequence
attr_reader :child
# このDeferredが成功した場合の処理を追加する。
# 新しいDeferredのインスタンスを返す。
# このメソッドはスレッドセーフです。
# TODO: procが空のとき例外を発生させる
def next(&proc)
add_child(Delayer::Deferred::Chain::Next.new(&proc))
end
alias deferred next
# このDeferredが失敗した場合の処理を追加する。
# 新しいDeferredのインスタンスを返す。
# このメソッドはスレッドセーフです。
# TODO: procが空のとき例外を発生させる
def trap(&proc)
add_child(Delayer::Deferred::Chain::Trap.new(&proc))
end
alias error trap
# この一連のDeferredをこれ以上実行しない。
# このメソッドはスレッドセーフです。
def cancel
change_sequence(:genocide) unless spoiled?
end
def has_child?
child ? true : false
end
# 子を追加する。
# _Delayer::Deferred::Chainable_ を直接指定できる。通常外部から呼ぶときは _next_ か _trap_ メソッドを使うこと。
# このメソッドはスレッドセーフです。
# ==== Args
# [chainable] 子となるDeferred
# ==== Return
# 必ず _chainable_ を返す
# ==== Raise
# [Delayer::Deferred::SequenceError]
# 既に子が存在している場合
def add_child(chainable)
change_sequence(:get_child) do
chainable.parent = self
@child = chainable
end
end
# 子が追加された時に一度だけコールバックするオブジェクトを登録する。
# observerと言っているが、実際には _Delayer::Deferred::Worker_ を渡して利用している。
# このメソッドはスレッドセーフです。
# ==== Args
# [observer] pushメソッドを備えているもの。引数に _@child_ の値が渡される
# ==== Return
# self
def add_child_observer(observer)
change_sequence(:gaze) do
@child_observer = observer
end
self
end
def awaited
@awaited ||= [].freeze
end
def has_awaited?
not awaited.empty?
end
def add_awaited(awaitable)
@awaited = [*awaited, awaitable].freeze
self
end
# activateメソッドを呼ぶDelayerジョブを登録する寸前に呼ばれる。
def reserve_activate
change_sequence(:reserve)
end
def enter_pass
change_sequence(:pass)
end
def exit_pass
change_sequence(:resume)
end
protected
# 親を再帰的に辿り、一番最初のノードを返す。
# 親が複数見つかった場合は、それらを返す。
def ancestor
if @parent
@parent.ancestor
else
self
end
end
# cancelとかデバッグ用のコールグラフを得るために親を登録しておく。
# add_childから呼ばれる。
def parent=(chainable)
@parent = chainable
end
private
def call_child_observer
if has_child? and defined?(@child_observer)
change_sequence(:called)
@child_observer.push(@child)
end
end
def on_sequence_changed(old_seq, flow, new_seq)
case new_seq
when NodeSequence::BURST_OUT
call_child_observer
when NodeSequence::GENOCIDE
@parent.cancel if defined?(@parent) and @parent
when NodeSequence::RESERVED_C, NodeSequence::RUN_C, NodeSequence::PASS_C, NodeSequence::AWAIT_C, NodeSequence::GRAFT_C
if !has_child?
notice "child: #{@child.inspect}"
raise Delayer::Deferred::SequenceError.new("Sequence changed `#{old_seq.name}' to `#{flow}', but it has no child")
end
end
end
# ノードの名前。サブクラスでオーバライドし、ノードが定義されたファイルの名前や行数などを入れておく。
def node_name
self.class.to_s
end
def graph_mynode
if defined?(@seq_logger)
label = "#{node_name}\n(#{@seq_logger.map(&:name).join('→')})"
else
label = "#{node_name}\n(#{sequence.name})"
end
"#{__id__} [shape=#{graph_shape},label=#{label.inspect}]"
end
end
end
# -*- coding: utf-8 -*-
module Delayer::Deferred::Deferredable
=begin rdoc
graphvizによってChainableなDeferredをDOT言語形式でダンプする機能を追加するmix-in。
いずれかのノードに対して _graph_ メソッドを呼ぶと、再帰的に親子を全て辿り、digraphの断片の文字列を得ることが出来る。
== 出力例
20892180 [shape=egg,label="#<Class:0x000000027da288>.Promise\n(reserved)"]
20892480 [shape=box,label="test/thread_test.rb:53\n(connected)"]
20891440 [shape=diamond,label="test/thread_test.rb:56\n(fresh)"]
20892480 -> 20891440
20892180 -> 20892480
=end
module Graph
# この一連のDeferredチェインの様子を、DOT言語フォーマットで出力する
# ==== Args
# [child_only:]
# _true_ なら、このノードとその子孫のみを描画する。
# _false_ なら、再帰的に親を遡り、そこから描画を開始する。
# [output:]
# このオブジェクトに、 _<<_ メソッドで内容が書かれる。
# 省略した場合は、戻り値が _String_ になる。
# ==== Return
# [String] DOT言語によるグラフ
# [output:] 引数 output: に指定されたオブジェクト
def graph(child_only: false, output: String.new)
if child_only
output << "digraph Deferred {\n".freeze
Enumerator.new{ |yielder|
graph_child(output: yielder)
}.lazy.each{|l|
output << "\t#{l}\n"
}
output << '}'.freeze
else
ancestor.graph(child_only: true, output: output)
end
end
# Graph.graph の結果を内容とする一時ファイルを作成して返す。
# ただし、ブロックを渡された場合は、一時ファイルを引数にそのブロックを一度だけ実行し、ブロックの戻り値をこのメソッドの戻り値とする。
# ==== Args
# [&block] 一時ファイルを利用する処理
# ==== Return
# [Tempfile] ブロックを指定しなかった場合。作成された一時ファイルオブジェクト
# [Object] ブロックが指定された場合。ブロックの実行結果。
def graph_save(permanent: false, &block)
if block
Tempfile.open{|tmp|
graph(output: tmp)
tmp.seek(0)
block.(tmp)
}
else
tmp = Tempfile.open
graph(output: tmp).tap{|t|t.seek(0)}
end
end
# 画像ファイルとしてグラフを書き出す。
# dotコマンドが使えないと失敗する。
# ==== Args
# [format:] 画像の拡張子
# ==== Return
# [String] 書き出したファイル名
def graph_draw(dir: '/tmp', format: 'svg'.freeze)
graph_save do |dotfile|
base = File.basename(dotfile.path)
dest = File.join(dir, "#{base}.#{format}")
system("dot -T#{format} #{dotfile.path} -o #{dest}")
dest
end
end
# このノードとその子全てのDeferredチェインの様子を、DOT言語フォーマットで出力する。
# Delayer::Deferred::Deferredable::Graph#graph の内部で利用されるため、将来このメソッドのインターフェイスは変更される可能性がある。
def graph_child(output:)
output << graph_mynode
if has_child?
@child.graph_child(output: output)
output << "#{__id__} -> #{@child.__id__}"
end
if has_awaited?