投稿日 2009年7月30日 木曜日 カテゴリ Python, テスト 投稿者 sugimotoコメント(0) » 

sugimoto です。

Pythonの単体テストのツール unittest を使ってみました。

1. まずはマニュアル通りに。。

Python – unittestのマニュアルから、TestSequenceFunctions を実行します。

# python testsequecefunctions.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK

普通に成功しましたね。

2. TestSuite を実行する

今度は複数のTestCaseからなる、TestSuiteを実行してみます。

TestCaseは同じものを使ったので、命名のセンスが悪くてすいません。。

2つのTestCaseをまとめて実行するTestSuite

[testsuite.py]

import unittest
import testsequecefunctions as TestSequenceFunctions
import testsequecefunctions2 as TestSequenceFunctions2

suite1 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions.TestSequenceFunctions)
suite2 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions2.TestSequenceFunctions2)
suite = unittest.TestSuite([suite1, suite2])
print suite.countTestCases()

runner = unittest.TextTestRunner()
runner.run(suite)

実行すると

# python testsuite.py
6
......
----------------------------------------------------------------------
Ran 6 tests in 0.002s

OK

6個のテストがすべてパスしました。

3. trac plugin をテストしてみる

trac のestimationtools pluginをテストしてみます。すでにテストコードも提供されているので、今回は実行するだけです。

# unzip estimationtoolsplugin-r6309.zip
# cd estimationtoolsplugin/trunk/estimationtools/tests
# ll
total 24
-rw-r--r-- 1 root root 9264 Jul 29 11:18 burndownchart.py
-rw-r--r-- 1 root root 2696 Jul 30 10:46 hoursremaining.py
-rw-r--r-- 1 root root 2283 Jan 26  2009 workloadchart.py

そのまま実行できるようにスクリプトの最後に以下のコードを追加しておきます。

if __name__ == "__main__":
    unittest.main()

そして実行

# python burndownchart.py
Traceback (most recent call last):
  File "burndownchart.py", line 3, in ?
    from estimationtools.burndownchart import BurndownChart
ImportError: No module named estimationtools.burndownchart

エラーになりました。。

estimationtools.burndownchart がないということですね。。

plugin 本体のディレクトリにパスを通しておきます。

# export PYTHONPATH=/root/plugins/estimationtoolsplugin/trunk/

再度実行します。

# python burndownchart.py
...FFF......
======================================================================
FAIL: test_calculate_timetable_with_closed_and_reopened_ticket (__main__.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "burndownchart.py", line 140, in test_calculate_timetable_with_closed_and_reopened_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0), day4: Decimal(5)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket (__main__.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "burndownchart.py", line 113, in test_calculate_timetable_with_closed_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(5), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("5"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket2 (__main__.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "burndownchart.py", line 126, in test_calculate_timetable_with_closed_ticket2
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

----------------------------------------------------------------------
Ran 12 tests in 0.478s

FAILED (failures=3)
#

今度はうまくいった。。と思ったら、なぜかテストが失敗しましたね。。

4. estimationtools plugin のtest suite を実行する

estimationtools plugin には3つのテストがあるので、すべて実行するためのスクリプトを作ります。

[testsuite.py]

import unittest
import burndownchart as burndownchart
import hoursremaining as hoursremaining
import workloadchart as workloadchart

runner = unittest.TextTestRunner()
suite = unittest.TestLoader().loadTestsFromTestCase(burndownchart.BurndownChartTestCase)
runner.run(suite)

suite = unittest.TestLoader().loadTestsFromTestCase(hoursremaining.HoursRemainingTestCase)
runner.run(suite)

suite = unittest.TestLoader().loadTestsFromTestCase(workloadchart.WorkloadChartTestCase)
runner.run(suite)

3つのテストをロードして、実行するだけです。簡単です。

実行してみます。

# python testsuite.py
...FFF......
======================================================================
FAIL: test_calculate_timetable_with_closed_and_reopened_ticket (burndownchart.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/plugins/estimationtoolsplugin/trunk/estimationtools/tests/burndownchart.py", line 140, in test_calculate_timetable_with_closed_and_reopened_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0), day4: Decimal(5)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket (burndownchart.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/plugins/estimationtoolsplugin/trunk/estimationtools/tests/burndownchart.py", line 113, in test_calculate_timetable_with_closed_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(5), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("5"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket2 (burndownchart.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/plugins/estimationtoolsplugin/trunk/estimationtools/tests/burndownchart.py", line 126, in test_calculate_timetable_with_closed_ticket2
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

----------------------------------------------------------------------
Ran 12 tests in 0.619s

FAILED (failures=3)
.....
----------------------------------------------------------------------
Ran 5 tests in 0.692s

OK
..
----------------------------------------------------------------------
Ran 2 tests in 0.126s

OK

1つめのテストケースはやっぱり失敗しますが、残りのテストケースはすべて成功しました。

今回は既存のplugin に添付されているテストケースを使いましたが、自分がpluginを作ったときもテストケースを書きたいと思います。

参考
投稿日 2009年7月30日 木曜日 カテゴリ javascript 投稿者 matsushitaコメント(0) » 

こんにちは。松下です。

開発版のサンプルページで既に紹介されているものもありますが、flotで描画したグラフにイベント処理を追加する方法を紹介します。

flotには、あらかじめマウスのホバーやクリック時のカスタムイベントが定義されており、このカスタムイベントに対してコールバック関数を紐付ければ、独自のイベントを追加することができます。

クリックイベントを追加する

flotでは、”plotclick”というグラフのポイントをクリックした時のカスタムイベントが定義されているので、以下のようなコードを書けば、ポインンクリック時の処理が追加することができます。

$("placeholder").bind("plotclick", function(event, pos, item) {
--略--
});

使用する上での前提条件は、plot描画時のgridオプションのclickableを有効にすること、seriesオプションのpointsを有効にすることです。

option = {
    series: {points:  {show: true}},
    grid: {clickable: true},
    --略--
};

以下に、グラフで描画したポイントで際に、ポイントをハイライトする処理を例示します。

$("#placeholder").bind("plotclick", function (event, pos, item) {
    if (item) {
        plot.highlight(item.series, item.datapoint);
    }
});

クリックすると以下のようにポイントがハイライトします。

before

after

windowリサイズにグラフをリロードする

単純に再プロットするなら以下のとおりで、windowリサイズ時に通常と同じように描画する処理をバインドするだけです。

$(window).resize(function() {
    var plot = $.plot($("#placeholder"), datalist, options);
});

なぜ、こんな処理を行うかというと、グラフを描画する領域のサイズを固定しない場合、グラフのラベルや判例がずれてしまうからです。以下の画面では、判例を左上に設定したにも関わらず、windowサイズを小さくしたことで判例が右側にずれています。

画面が崩れる

この問題をリサイズ時に描画処理を行うことで問題を解決できます。

しかしながら、この処理には少し不満に思いました。理由は、再描画を処理的にはcanvasオブジェクトを再作成してデータを描画してといった処理を一からやり直すことになるので、windowサイズが変更されるたびに行う処理として少しコストが高い処理だと思ったからです。

そこで、初期化処理を行うことなくリサイズ処理だけ行うことはできないか、調査してみました。 が、結論からいうとコードの作り上、どうしようもないことがわかりました。 グラフの描画処理は

var plot = $.plot($("#placeholder"), datalist, options);

のように行いますが、plot関数実行後に内部で生成したPlotクラスが返却されます。 これを使って、以下のように実行できないか試してみましたが、グラフのリサイズは行われない模様。

    var plot = $.plot($("#placeholder"), datalist, options);
    plot.setupGrid();
    plot.draw();

でさらに調べてみると、初期化処理において、canvasWidth、canvasHeightという内部変数を設定しており、グラフの描画処理はこれらの変数に依存していることが分かりました。これらの変数をwindowリサイズ時に再設定すれば良いのですが、これらの変数を外部から書き換える手段、及びタイミングが存在しません。

で苦肉の策ですが、Plotクラスの内部関数であるconstructCanvasでcanvasWidth、canvasHeightを設定する処理を行っているので、これを外部公開するようにflotのコードを修正した上で、以下のコードを実行。

    var plot = $.plot($("#placeholder"), datalist, options);
    plot.constructCanvas();
    plot.setupGrid();
    plot.draw();

これはうまく行きました。reloadとかメソッドがあればいいんですが、今のところこの方法と同様にflot自体に手を加える方法しかないようです。

自分がflotを使っていて思ったのが、今回みたいにイベントを追加したりする場合に、今のflotがユーザに公開されている情報(メソッドやフィールド)が必要不十分であること。highlightメソッド、unhighlightメソッドはあるのに、外部からはどこがハイライトされているのか、ハイライトしていないのか分からないとか。 開発版なのでしょうがないのかもしれませんが、グラフライブラリとしては良いものだと思っているので、今後の改善に期待したいと思ってます。

記事を読んでくださった方で、他になにか方法があれば教えてください。

投稿日 2009年7月28日 火曜日 カテゴリ Active Directory 投稿者 omaeコメント(0) » 

omae です。Active Directory で管理しているオブジェクトをコマンドラインから参照できるコマンドがあるのですが、毎回「なんて名前だっけ…」と忘れてしまうので、メモを兼ねて書いておきます。

Windows Server 2003 以降には dsquery というコマンドが標準で入っており、このコマンドで Active Directory をクエリできます。

Builtin コンテナにあるオブジェクトをクエリするには以下のコマンドを実行します。

C:\>dsquery * "CN=Builtin,DC=opengroove,DC=local"
"CN=Builtin,DC=opengroove,DC=local"
"CN=Administrators,CN=Builtin,DC=opengroove,DC=local"
"CN=Users,CN=Builtin,DC=opengroove,DC=local"
"CN=Guests,CN=Builtin,DC=opengroove,DC=local"
"CN=Print Operators,CN=Builtin,DC=opengroove,DC=local"
"CN=Backup Operators,CN=Builtin,DC=opengroove,DC=local"
"CN=Replicator,CN=Builtin,DC=opengroove,DC=local"
"CN=Remote Desktop Users,CN=Builtin,DC=opengroove,DC=local"
"CN=Network Configuration Operators,CN=Builtin,DC=opengroove,DC=local"
"CN=Performance Monitor Users,CN=Builtin,DC=opengroove,DC=local"
"CN=Performance Log Users,CN=Builtin,DC=opengroove,DC=local"
"CN=Distributed COM Users,CN=Builtin,DC=opengroove,DC=local"
"CN=Server Operators,CN=Builtin,DC=opengroove,DC=local"
"CN=Account Operators,CN=Builtin,DC=opengroove,DC=local"
"CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=opengroove,DC=local"
"CN=Incoming Forest Trust Builders,CN=Builtin,DC=opengroove,DC=local"
"CN=Windows Authorization Access Group,CN=Builtin,DC=opengroove,DC=local"
"CN=Terminal Server License Servers,CN=Builtin,DC=opengroove,DC=local"

特定アカウント(ここでは Guest アカウント)の属性をクエリするには -attr * を付けます。

C:\>dsquery * "CN=Guest,CN=Users,DC=opengroove,DC=local" -attr *
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Guest
description: コンピュータ/ドメインへのゲスト アクセス用 (ビルトイン アカウント)
distinguishedName: CN=Guest,CN=Users,DC=opengroove,DC=local
instanceType: 4
whenCreated: 05/10/2007 07:53:23
whenChanged: 05/10/2007 07:53:23
uSNCreated: 8195
memberOf: CN=Guests,CN=Builtin,DC=opengroove,DC=local
uSNChanged: 8195
name: Guest
objectGUID: {C5D1E20D-00C1-498B-952B-CF86FA8682E2}
userAccountControl: 66082
badPwdCount: 2
codePage: 0
countryCode: 0
badPasswordTime: 128856403556663503
lastLogoff: 0
lastLogon: 0
pwdLastSet: 0
primaryGroupID: 514
objectSid: S-1-5-21-1910479612-2582990179-2480390514-501
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: Guest
sAMAccountType: 805306368
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=opengroove,DC=local
isCriticalSystemObject: TRUE
ADsPath: LDAP://sancha.opengroove.local/CN=Guest,CN=Users,DC=opengroove,DC=local

実際にやりたかったのは msDS-KeyVersionNumber の値を確認したかったのでした。この場合には -attr msDS-KeyVersionNumber を指定します。

C:\>dsquery * "CN=Guest,CN=Users,DC=opengroove,DC=local" -attr msDS-KeyVersionNumber
  msDS-KeyVersionNumber
  1

dsquery 以外にも Active Directory を操作するためのコマンドが用意されています。 また、特にコマンドラインでないといけないという制限がないのであれば Adsiedit でやるとよいでしょう。いつもはこの Adsiedit で確認しています。

参考

投稿日 2009年7月25日 土曜日 カテゴリ Trac, ソフトウェア開発 投稿者 syojiComments Off 

開発の現場で大きく2種類の声を聞くことが多い。

ひとつは、「バージョン管理は必須で、プロジェクトが始まったらすぐにリポジトリを作成する」という利用者の声。

もうひとつが「まったく使ったことがない」「使いたいけど、教育が・・・」「自分でバージョン管理(フォルダに日付・・・)」などの利用したことがない人の声。

自分が話を聞いたり、見たりした開発の現場では、特にエンタープライズ系の開発においてバージョン管理システムを導入していないところが多かった気がする。

バージョン管理システムとは

バージョン管理システムとは、プログラムを開発するとき、主にプログラムの版(バージョン)を管理するためのツールである。ファイルの階層構造全体はリポジトリと呼ばれる場所(サーバ)に置かれ、ファイルやフォルダに対するすべての追加、変更、削除を記録する。ファイルの中身に対する変更だけでなく、ファイル名、フォルダ名に対する変更も記録する。

リポジトリに記録された履歴は、古いバージョンのソースコードを参照したり、取り出したりすることができる。 これによって、過去のソースコードに対する修正内容、障害対応時の変更理由、リリース後に発生した不具合の調査など開発者にとってとても便利な機能である。

主なバージョン管理システムは、CVS,Subversion,git などのオープンソースから製品版まで多くの種類がある。

最近では、CVS,Subversionといった中央のリポジトリで管理する仕組みから、SVKgit(Linuxカーネルの開発で使用) など分散バージョン管理がはやっているようだ。

プログラム開発で縁の下の力持ち的に力を発揮するバージョン管理システムであるが、どのようなツールでも言えることであるが

  • 利用目的
  • 運用とルール

を決めておくことが重要である。

以前のブログ記事で「バグトラッキングシステムのワークフロー」について説明したが、新機能開発の時/障害対応の時とワークフローを決めておくことが重要である。 バージョン管理システムとバグトラッキングシステムを密に連携させて管理することで、ものすごい恩恵を受けることが出来ると思う。

バージョン管理とバグトラッキング(BTS)

バージョン管理とバグトラッキング(BTS)

「導入するためには上司を納得させないと・・・」「チームメンバーの教育コストが・・・」など障壁はあるかもしれないが、その障壁を乗り越えて余りあるメリットがある。 開発現場のリーダーや開発チームに提案してみようと考えている人はぜひ導入に向けて頑張って欲しいと思う。

参考になるサイト:

投稿日 2009年7月23日 木曜日 カテゴリ Python 投稿者 morimotoコメント(0) » 

こんばんわ。morimotoです。

前回の数値判定の関数を一括してテストするためにテストクラスを書いてみました。 少々汚いですが暴動とかデモとか起こさないでください。。。

まずはテストクラス function_test.py

# -*- coding: utf-8 -*-
class FunctionTest:
    def display_all(self, tests={}):
        for namespace in tests:
            print ""
            print "*" * 15 + (namespace + " Tests").center(30) + "*" * 15
            print ""
            cases = tests.get(namespace, [])
            for case in cases:
                functions = case.get('functions', [])
                args_list = case.get('args_list', [])
                args_default = case.get('args_default', {})
                self.display(namespace, functions, args_list, args_default)

    def display(self, namespace, functions, args_list, args_default={}):
        if functions:
            format, sep = self.get_format(functions[:], args_list[:])
            if args_default:
                print " * set args default values : %s" % ",".join([" %s = %s"%(name, args_default[name],) for name in args_default])
            print sep
            print format % (('args',) + tuple(functions[:]))
            print sep
            for args in args_list:
                print format % ((str(args),) + tuple([self.execute(namespace, func, args, args_default) for func in functions[:]]))
            print sep
            print ''

    def get_format(self, functions, args_list):
        ph = lambda v: '%' + '%s'%v + 's'
        args_len = args_list and max([len(str(args)) for args in args_list[:]]) or 0
        func_lens = [len(str(func)) for func in functions[:]]
        format = '| ' + ph(args_len) + ' || ' + ' | '.join([ph(fl) for fl in func_lens[:]]) + ' |'
        sep = '+' + '-' * (args_len + 2) + '++' + '+'.join(['-' * (fl+2) for fl in func_lens[:]]) + '+'
        return format, sep

    def execute(self, namespace, function_name, args, args_default={}):
        my_module = __import__(namespace)
        my_func = getattr(my_module, function_name)
        return apply(my_func, self.args_to_tuple(args), self.args_to_dict(args, args_default))

    def args_to_tuple(self, args):
        if isinstance(args, tuple):
            return args
        if isinstance(args, list):
            return tuple(args)
        if isinstance(args, str):
            return tuple([args,])
        return tuple([])
    
    def args_to_dict(self, args, args_default={}):
        if isinstance(args, dict):
            args.update(args_default)
            return args
        return args_default

前回のutilities.py (try-catch でパースするのもテストしてみる)

# -*- coding: utf-8 -*-
import re

# Convert functions
def parseInt(value, default=None):
    (ret,) = validates_integer_of(value) and (int(value),) or \
            (validates_number_of(value) and (int(float(value)),) or (default,))
    return ret

def _parseInt(value, default=None):
    try:
        return int(value)
    except:
        return default

# Validate functions
def validates_number_of(value):
    return re.match(r'^(?![-+]0+$)[-+]?([1-9][0-9]*)?[0-9](\.[0-9]+)?$', '%s'%value) and True or False

def validates_integer_of(value):
    return re.match(r'^(?![-+]0*$)[-+]?([1-9][0-9]*)?0?$', '%s'%value) and True or False

def validates_float_of(value):
    return validates_number_of(value) and not validates_integer_of(value) or False

最後にテストするための test.py

# -*- coding: utf-8 -*-
from function_test import FunctionTest
from utilities import *

test_values = [
    "123456",
    "0",
    "-9",
    "+5",
    "+9",
    "0.0000",
    "1234.56",
    "-123.45",
    "+123.45",
    "-0.123",
    "123.00000",
    "+00000000",
    "-00000000",
    "+0",
    "-0",
    "ABCDEF",
    "1+23",
    "123-",
    "-.123",
    "123.",
    "00012",
    ".123",
    "+0000",
    "-0000",
    "+0000.22",
    "+",
    "-",
    ["12345"],
    ("12345",),
    {"value": "12345"},
]

test_functions = {
    'utilities': [
        {
            'functions': ['validates_number_of', 'validates_integer_of', 'validates_float_of', ],
            'args_list': test_values,
        },
        {
            'functions': ['parseInt', '_parseInt', ],
            'args_list': test_values,
            'args_default': { 'default': None, },
        },
   ]
}

ft = FunctionTest()
ft.display_all(test_functions)

  • test_functions の ‘utilities’ の部分は最初にimportしているテストしたい名前空間名。
  • 配列中の dictionary は引数が同じ(出来れば引数の数や名前が同じ)場合はまとめてしまって構わないです。
  • ‘functions’ は名前の通り関数名のリスト
  • ‘args_list’ はテストしたい引数のリスト。
  • ‘args_default’ は任意で値をセットしたい場合に引数名をキーに対して値を入れる。
  • test_values の下3つはテストクラスのテスト用(笑)
  • この3つのファイルを同じ階層に置いていただき、後はコンソールから

    python test.py
    

    を実行するだけです。

    結果

    >python test.py
    
    ***************       utilities Tests        ***************
    
    +--------------------++---------------------+----------------------+--------------------+
    |               args || validates_number_of | validates_integer_of | validates_float_of |
    +--------------------++---------------------+----------------------+--------------------+
    |             123456 ||                True |                 True |              False |
    |                  0 ||                True |                 True |              False |
    |                 -9 ||                True |                 True |              False |
    |                 +5 ||                True |                 True |              False |
    |                 +9 ||                True |                 True |              False |
    |             0.0000 ||                True |                False |               True |
    |            1234.56 ||                True |                False |               True |
    |            -123.45 ||                True |                False |               True |
    |            +123.45 ||                True |                False |               True |
    |             -0.123 ||                True |                False |               True |
    |          123.00000 ||                True |                False |               True |
    |          +00000000 ||               False |                False |              False |
    |          -00000000 ||               False |                False |              False |
    |                 +0 ||               False |                False |              False |
    |                 -0 ||               False |                False |              False |
    |             ABCDEF ||               False |                False |              False |
    |               1+23 ||               False |                False |              False |
    |               123- ||               False |                False |              False |
    |              -.123 ||               False |                False |              False |
    |               123. ||               False |                False |              False |
    |              00012 ||               False |                False |              False |
    |               .123 ||               False |                False |              False |
    |              +0000 ||               False |                False |              False |
    |              -0000 ||               False |                False |              False |
    |           +0000.22 ||               False |                False |              False |
    |                  + ||               False |                False |              False |
    |                  - ||               False |                False |              False |
    |          ['12345'] ||                True |                 True |              False |
    |         ('12345',) ||                True |                 True |              False |
    | {'value': '12345'} ||                True |                 True |              False |
    +--------------------++---------------------+----------------------+--------------------+
    
     * set args default values :  default = None
    +--------------------++----------+-----------+
    |               args || parseInt | _parseInt |
    +--------------------++----------+-----------+
    |             123456 ||   123456 |    123456 |
    |                  0 ||        0 |         0 |
    |                 -9 ||       -9 |        -9 |
    |                 +5 ||        5 |         5 |
    |                 +9 ||        9 |         9 |
    |             0.0000 ||        0 |      None |
    |            1234.56 ||     1234 |      None |
    |            -123.45 ||     -123 |      None |
    |            +123.45 ||      123 |      None |
    |             -0.123 ||        0 |      None |
    |          123.00000 ||      123 |      None |
    |          +00000000 ||     None |         0 |
    |          -00000000 ||     None |         0 |
    |                 +0 ||     None |         0 |
    |                 -0 ||     None |         0 |
    |             ABCDEF ||     None |      None |
    |               1+23 ||     None |      None |
    |               123- ||     None |      None |
    |              -.123 ||     None |      None |
    |               123. ||     None |      None |
    |              00012 ||     None |        12 |
    |               .123 ||     None |      None |
    |              +0000 ||     None |         0 |
    |              -0000 ||     None |         0 |
    |           +0000.22 ||     None |      None |
    |                  + ||     None |      None |
    |                  - ||     None |      None |
    |          ['12345'] ||    12345 |     12345 |
    |         ('12345',) ||    12345 |     12345 |
    | {'value': '12345'} ||    12345 |     12345 |
    +--------------------++----------+-----------+
    

    _parseInt のほうはボロボロでした。 int()よ、しっかりしてください・・・。

    以上morimotoでした。

    次のページ »