diff -Nru pybik-1.0.2~alpha1~bzr1545/data/applications/pybik.desktop pybik-1.0.2~alpha1~bzr1549/data/applications/pybik.desktop --- pybik-1.0.2~alpha1~bzr1545/data/applications/pybik.desktop 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/data/applications/pybik.desktop 2013-02-28 16:46:46.000000000 +0000 @@ -9,6 +9,7 @@ Name[ky]=Pybik Name[ms]=Pybik Name[pt_BR]=Pybik +Name[sr]=Питонова коцка Name[uk]=Pybik Comment=3D Rubik's cube game Comment[de]=Ein 3D-Zauberwürfelspiel @@ -27,6 +28,6 @@ Categories=Game;LogicGame; # Add whatever keywords you want in your language, separated by semicolons. These keywords are used when searching for applications in dashes, etc. (Unity, GNOME Shell) Keywords=rubik;cube;puzzle;magic; -Keywords[de]=rubik;würfel;puzzle;zauberwürfel; +Keywords[de]=rubik;cube;würfel;puzzle;zauberwürfel; StartupNotify=true X-Ubuntu-Gettext-Domain=pybik diff -Nru pybik-1.0.2~alpha1~bzr1545/debian/bzr-builder.manifest pybik-1.0.2~alpha1~bzr1549/debian/bzr-builder.manifest --- pybik-1.0.2~alpha1~bzr1545/debian/bzr-builder.manifest 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/debian/bzr-builder.manifest 2013-02-28 16:46:47.000000000 +0000 @@ -1,2 +1,2 @@ -# bzr-builder format 0.3 deb-version {debupstream}~bzr1545-0 -lp:pybik revid:barcc@gmx.de-20130217195453-bf2qhqvb3u92gxb9 +# bzr-builder format 0.3 deb-version {debupstream}~bzr1549-0 +lp:pybik revid:barcc@gmx.de-20130228163053-9zzj77xjmyite3ae diff -Nru pybik-1.0.2~alpha1~bzr1545/debian/changelog pybik-1.0.2~alpha1~bzr1549/debian/changelog --- pybik-1.0.2~alpha1~bzr1545/debian/changelog 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/debian/changelog 2013-02-28 16:46:47.000000000 +0000 @@ -1,8 +1,8 @@ -pybik (1.0.2~alpha1~bzr1545-0~precise1) precise; urgency=low +pybik (1.0.2~alpha1~bzr1549-0~precise1) precise; urgency=low * Auto build. - -- B Clausius Mon, 18 Feb 2013 03:54:21 +0000 + -- B Clausius Thu, 28 Feb 2013 16:46:47 +0000 pybik (1.0.2~alpha1-0~ppa1) UNRELEASED; urgency=low diff -Nru pybik-1.0.2~alpha1~bzr1545/po/de.po pybik-1.0.2~alpha1~bzr1549/po/de.po --- pybik-1.0.2~alpha1~bzr1545/po/de.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/de.po 2013-02-28 16:46:46.000000000 +0000 @@ -8,16 +8,16 @@ "Project-Id-Version: pybik\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/pybik/+filebug\n" "POT-Creation-Date: 2013-01-31 14:25+0100\n" -"PO-Revision-Date: 2012-12-15 00:22+0000\n" -"Last-Translator: B Clausius \n" +"PO-Revision-Date: 2013-02-01 09:44+0000\n" +"Last-Translator: B Clausius \n" "Language-Team: German\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Launchpad-Export-Date: 2012-12-16 04:59+0000\n" -"X-Generator: Launchpad (build 16372)\n" +"X-Launchpad-Export-Date: 2013-02-02 05:11+0000\n" +"X-Generator: Launchpad (build 16462)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -530,7 +530,7 @@ #. Add whatever keywords you want in your language, separated by semicolons. These keywords are used when searching for applications in dashes, etc. (Unity, GNOME Shell) #: ../data/applications/pybik.desktop.in.h:4 msgid "rubik;cube;puzzle;magic;" -msgstr "rubik;würfel;puzzle;zauberwürfel;" +msgstr "rubik;cube;würfel;puzzle;zauberwürfel;" #: ../data/plugins/01-challenges.algorithm.py:19 #: ../data/plugins/01-challenges.algorithm.py:22 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/en_GB.po pybik-1.0.2~alpha1~bzr1549/po/en_GB.po --- pybik-1.0.2~alpha1~bzr1545/po/en_GB.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/en_GB.po 2013-02-28 16:46:46.000000000 +0000 @@ -16,8 +16,8 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Launchpad-Export-Date: 2013-01-16 04:47+0000\n" -"X-Generator: Launchpad (build 16420)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" diff -Nru pybik-1.0.2~alpha1~bzr1545/po/es.po pybik-1.0.2~alpha1~bzr1549/po/es.po --- pybik-1.0.2~alpha1~bzr1545/po/es.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/es.po 2013-02-28 16:46:46.000000000 +0000 @@ -8,15 +8,16 @@ "Project-Id-Version: pybik\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/pybik/+filebug\n" "POT-Creation-Date: 2013-01-31 14:25+0100\n" -"PO-Revision-Date: 2013-01-13 06:46+0000\n" +"PO-Revision-Date: 2013-02-02 22:30+0000\n" "Last-Translator: Adolfo Jayme Barrientos \n" "Language-Team: Spanish \n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Launchpad-Export-Date: 2013-01-14 04:40+0000\n" -"X-Generator: Launchpad (build 16420)\n" +"X-Launchpad-Export-Date: 2013-02-03 04:52+0000\n" +"X-Generator: Launchpad (build 16462)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -103,17 +104,15 @@ #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" #: ../pybiklib/dialogs.py:168 @@ -198,7 +197,7 @@ #: ../pybiklib/model.py:215 msgid "{0}×{1}×{2}-Brick" -msgstr "" +msgstr "{0}×{1}×{2}-Bloque" #: ../pybiklib/model.py:835 msgid "Tower" @@ -206,7 +205,7 @@ #: ../pybiklib/model.py:836 msgid "{0}×{1}-Tower" -msgstr "" +msgstr "{0}×{1}-Torre" #: ../pybiklib/model.py:850 msgid "Cube" @@ -214,7 +213,7 @@ #: ../pybiklib/model.py:851 msgid "{0}×{0}×{0}-Cube" -msgstr "" +msgstr "{0}×{0}×{0}-Cubo" #: ../pybiklib/plugins.py:92 msgid "This algorithm does not work for any model.\n" @@ -283,7 +282,7 @@ #: ../pybiklib/ui/main.py:203 msgid "&Select Model …" -msgstr "" +msgstr "&Seleccionar modelo…" #: ../pybiklib/ui/main.py:204 msgid "&Set as Initial State" @@ -315,7 +314,7 @@ #: ../pybiklib/ui/main.py:211 msgid "&Info …" -msgstr "" +msgstr "&Información…" #: ../pybiklib/ui/main.py:212 msgid "Rewind" @@ -721,7 +720,7 @@ #: ../data/plugins/80-pretty-patterns.algorithm.py:40 #: ../data/plugins/80-pretty-patterns.algorithm.py:44 msgid "Stripes" -msgstr "" +msgstr "Rayas" #: ../data/plugins/80-pretty-patterns.algorithm.py:49 #: ../data/plugins/80-pretty-patterns.algorithm.py:53 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/fr.po pybik-1.0.2~alpha1~bzr1549/po/fr.po --- pybik-1.0.2~alpha1~bzr1545/po/fr.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/fr.po 2013-02-28 16:46:46.000000000 +0000 @@ -11,12 +11,13 @@ "PO-Revision-Date: 2013-01-08 12:53+0000\n" "Last-Translator: Aurélien Ribeiro \n" "Language-Team: French \n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Launchpad-Export-Date: 2013-01-09 05:14+0000\n" -"X-Generator: Launchpad (build 16412)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -107,17 +108,15 @@ #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" #: ../pybiklib/dialogs.py:168 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/gl.po pybik-1.0.2~alpha1~bzr1549/po/gl.po --- pybik-1.0.2~alpha1~bzr1545/po/gl.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/gl.po 2013-02-28 16:46:46.000000000 +0000 @@ -11,12 +11,13 @@ "PO-Revision-Date: 2012-12-20 10:28+0000\n" "Last-Translator: Miguel Anxo Bouzada \n" "Language-Team: Galician \n" +"Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Launchpad-Export-Date: 2012-12-21 05:03+0000\n" -"X-Generator: Launchpad (build 16378)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -64,8 +65,8 @@ "collection of various moves. The cube can be manipulated with the mouse or " "keyboard. You can change the colors or images on the faces of the cube." msgstr "" -"Pybik é un crebacabezas gráfico e interactivo, baseado no cubo inventado por " -" Ernő Rubik. Ademais do cubo, o programa pode manexar torres e ladrillos " +"Pybik é un crebacabezas gráfico e interactivo, baseado no cubo inventado " +"por Ernő Rubik. Ademais do cubo, o programa pode manexar torres e ladrillos " "(crebacabezas que non son cúbicos). Pybik dispón tamén de solucionadores, " "modelos agradábeis e unha colección de movementos. O cubo pode manipularse " "co rato ou co teclado. Vostede pode cambiarlle as cores ou as imaxes nas " @@ -121,29 +122,25 @@ #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" -"As traducións son xestionadas polo " -"Grupo de " -"tradución de Launchpad<|>.\n" +"As traducións son xestionadas polo Grupo de tradución de Launchpad<|>.\n" "\n" -"Se quere axudar na tradución do Pybik ao seu idioma pode facelos na " -"interface web<|>.\n" +"Se quere axudar na tradución do Pybik ao seu idioma pode facelos na interface web<|>.\n" "\n" "Bótelle unha ollada a \"Traducindo " -"co Launchpad\"<|> e " -"\"Comezar a " -"traducir\"<|>." +"co Launchpad\"<|> e \"Comezar a traducir\"<|>." #: ../pybiklib/dialogs.py:168 msgid "Press a key …" @@ -255,8 +252,7 @@ #: ../pybiklib/settings.py:256 msgid "Settings can not be written to file: {error_message}" -msgstr "" -"Non foi posíbel gardar as configuracións no ficheiro: {error_message}" +msgstr "Non foi posíbel gardar as configuracións no ficheiro: {error_message}" #: ../pybiklib/ui/about.py:131 msgid "About Pybik" diff -Nru pybik-1.0.2~alpha1~bzr1545/po/he.po pybik-1.0.2~alpha1~bzr1549/po/he.po --- pybik-1.0.2~alpha1~bzr1545/po/he.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/he.po 2013-02-28 16:46:46.000000000 +0000 @@ -11,12 +11,13 @@ "PO-Revision-Date: 2013-01-08 13:42+0000\n" "Last-Translator: Yaron \n" "Language-Team: Hebrew \n" +"Language: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Launchpad-Export-Date: 2013-01-09 05:14+0000\n" -"X-Generator: Launchpad (build 16412)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -112,35 +113,31 @@ "please submit a <{CONTACT_FILEBUG}|>bug report<|>. In the latter case you " "can mark the bug report as \"Wishlist\"." msgstr "" -"אם מצאת תקלות ב־Pybik או שיש לך הצעות לשיפורים נא לשלוח " -"<{CONTACT_FILEBUG}|>דיווח על תקלה<|>. במקרה השני שצוין ניתן לסמן את התקלה " -"בתור „משאלה“ (Wishlist)" +"אם מצאת תקלות ב־Pybik או שיש לך הצעות לשיפורים נא לשלוח <{CONTACT_FILEBUG}|" +">דיווח על תקלה<|>. במקרה השני שצוין ניתן לסמן את התקלה בתור " +"„משאלה“ (Wishlist)" #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" -"התרגומים מנוהלים באמצעות " -"קבוצת " -"התרגום של לאנצ׳פד<|>.\n" +"התרגומים מנוהלים באמצעות קבוצת התרגום של לאנצ׳פד<|>.\n" "\n" -"אם בא לך לסייע בתרגום Pybik לשפתך ניתן לעשות זאת דרך " -"המנשק המקוון<|>.\n" +"אם בא לך לסייע בתרגום Pybik לשפתך ניתן לעשות זאת דרך המנשק המקוון<|>.\n" "\n" "ניתן לקרוא עוד על \"תרגום עם " -"לאנצ׳פד\"<|> ועל " -"\"כיצד מתחילים " -"לתרגם\"<|>." +"לאנצ׳פד\"<|> ועל \"כיצד מתחילים לתרגם\"<|>." #: ../pybiklib/dialogs.py:168 msgid "Press a key …" diff -Nru pybik-1.0.2~alpha1~bzr1545/po/ky.po pybik-1.0.2~alpha1~bzr1549/po/ky.po --- pybik-1.0.2~alpha1~bzr1545/po/ky.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/ky.po 2013-02-28 16:46:46.000000000 +0000 @@ -9,14 +9,15 @@ "Report-Msgid-Bugs-To: https://bugs.launchpad.net/pybik/+filebug\n" "POT-Creation-Date: 2013-01-31 14:25+0100\n" "PO-Revision-Date: 2012-12-14 10:00+0000\n" -"Last-Translator: blacktext \n" +"Last-Translator: Chynggyz Jumaliev \n" "Language-Team: Kirghiz \n" +"Language: ky\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Launchpad-Export-Date: 2012-12-16 04:59+0000\n" -"X-Generator: Launchpad (build 16372)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -99,17 +100,15 @@ #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" #: ../pybiklib/dialogs.py:168 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/ms.po pybik-1.0.2~alpha1~bzr1549/po/ms.po --- pybik-1.0.2~alpha1~bzr1545/po/ms.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/ms.po 2013-02-28 16:46:46.000000000 +0000 @@ -11,12 +11,13 @@ "PO-Revision-Date: 2012-12-23 03:45+0000\n" "Last-Translator: abuyop \n" "Language-Team: Malay \n" +"Language: ms\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Launchpad-Export-Date: 2012-12-24 04:43+0000\n" -"X-Generator: Launchpad (build 16378)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -101,17 +102,15 @@ #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" #: ../pybiklib/dialogs.py:168 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/pt_BR.po pybik-1.0.2~alpha1~bzr1549/po/pt_BR.po --- pybik-1.0.2~alpha1~bzr1545/po/pt_BR.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/pt_BR.po 2013-02-28 16:46:46.000000000 +0000 @@ -11,12 +11,13 @@ "PO-Revision-Date: 2012-12-14 14:05+0000\n" "Last-Translator: Rafael Neri \n" "Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Launchpad-Export-Date: 2012-12-16 04:59+0000\n" -"X-Generator: Launchpad (build 16372)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -101,17 +102,15 @@ #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" #: ../pybiklib/dialogs.py:168 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/ru.po pybik-1.0.2~alpha1~bzr1549/po/ru.po --- pybik-1.0.2~alpha1~bzr1545/po/ru.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/ru.po 2013-02-28 16:46:46.000000000 +0000 @@ -17,8 +17,8 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Launchpad-Export-Date: 2012-12-16 04:59+0000\n" -"X-Generator: Launchpad (build 16372)\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" diff -Nru pybik-1.0.2~alpha1~bzr1545/po/sr.po pybik-1.0.2~alpha1~bzr1549/po/sr.po --- pybik-1.0.2~alpha1~bzr1545/po/sr.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/sr.po 2013-02-28 16:46:46.000000000 +0000 @@ -1,24 +1,23 @@ # Serbian translation for pybik # Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 # This file is distributed under the same license as the pybik package. -# FIRST AUTHOR , 2011. -# +# Мирослав Николић , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: pybik\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/pybik/+filebug\n" "POT-Creation-Date: 2013-01-31 14:25+0100\n" -"PO-Revision-Date: 2011-08-03 15:38+0000\n" +"PO-Revision-Date: 2013-02-27 13:26+0000\n" "Last-Translator: Мирослав Николић \n" -"Language-Team: Serbian \n" +"Language-Team: Serbian \n" "Language: sr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Launchpad-Export-Date: 2012-12-16 04:59+0000\n" -"X-Generator: Launchpad (build 16372)\n" +"X-Launchpad-Export-Date: 2013-02-28 04:55+0000\n" +"X-Generator: Launchpad (build 16506)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -28,17 +27,18 @@ #: ../pybiklib/application.py:313 msgid "{current} / {total} move" msgid_plural "{current} / {total} moves" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{current} / {total} потез" +msgstr[1] "{current} / {total} потеза" +msgstr[2] "{current} / {total} потеза" #. substitution for {solved_text} in statusbar text #: ../pybiklib/application.py:317 ../pybiklib/ui/model.py:82 msgid "solved" -msgstr "" +msgstr "решено" #: ../pybiklib/application.py:317 msgid "not solved" -msgstr "" +msgstr "није решено" #. statusbar text #: ../pybiklib/application.py:320 @@ -52,7 +52,7 @@ #: ../pybiklib/config.py:30 ../pybiklib/ui/main.py:194 #: ../data/applications/pybik.desktop.in.h:1 msgid "Pybik" -msgstr "" +msgstr "Питонова коцка" #: ../pybiklib/config.py:59 ../data/applications/pybik.desktop.in.h:2 msgid "3D Rubik's cube game" @@ -91,6 +91,8 @@ "You should have received a copy of the GNU General Public License along with " "this program. If not, see ." msgstr "" +"Требали сте да примите примерак Гнуове опште јавне лиценце уз овај програм. " +"Ако нисте, погледајте ." #: ../pybiklib/config.py:88 msgid "" @@ -118,7 +120,7 @@ #: ../pybiklib/dialogs.py:296 msgid "plain" -msgstr "" +msgstr "обично" #: ../pybiklib/dialogs.py:301 msgid "select …" @@ -126,27 +128,27 @@ #: ../pybiklib/dialogs.py:313 msgid "Up" -msgstr "" +msgstr "Горе" #: ../pybiklib/dialogs.py:313 msgid "Down" -msgstr "" +msgstr "Доле" #: ../pybiklib/dialogs.py:313 msgid "Left" -msgstr "" +msgstr "Лево" #: ../pybiklib/dialogs.py:313 msgid "Right" -msgstr "" +msgstr "Десно" #: ../pybiklib/dialogs.py:313 msgid "Front" -msgstr "" +msgstr "Спреда" #: ../pybiklib/dialogs.py:313 msgid "Back" -msgstr "" +msgstr "Отпозади" #: ../pybiklib/dialogs.py:331 msgid "Move" @@ -162,7 +164,7 @@ #: ../pybiklib/dialogs.py:536 ../pybiklib/ui/model.py:79 msgid "Size:" -msgstr "" +msgstr "Величина:" #: ../pybiklib/dialogs.py:536 msgid "Basis:" @@ -320,7 +322,7 @@ #: ../pybiklib/ui/main.py:213 msgid "Go to the previous mark (or the beginning) of the sequence of moves" -msgstr "" +msgstr "Идите на следећи знак (или на крај) у низу потеза" #: ../pybiklib/ui/main.py:214 msgid "Previous" @@ -328,7 +330,7 @@ #: ../pybiklib/ui/main.py:215 msgid "Make one step backwards" -msgstr "" +msgstr "Вратите се један потез уназад" #: ../pybiklib/ui/main.py:216 msgid "Stop" @@ -336,7 +338,7 @@ #: ../pybiklib/ui/main.py:217 msgid "Stop running the sequence of moves" -msgstr "" +msgstr "Зауставите извршавање низа потеза" #: ../pybiklib/ui/main.py:218 msgid "Play" @@ -344,7 +346,7 @@ #: ../pybiklib/ui/main.py:219 msgid "Run forward through the sequence of moves" -msgstr "" +msgstr "Покрените унапред кроз низ потеза" #: ../pybiklib/ui/main.py:220 msgid "Next" @@ -352,7 +354,7 @@ #: ../pybiklib/ui/main.py:221 msgid "Make one step forwards" -msgstr "" +msgstr "Начините један потез унапред" #: ../pybiklib/ui/main.py:222 msgid "Forward" @@ -360,7 +362,7 @@ #: ../pybiklib/ui/main.py:223 msgid "Go to the next mark (or the end) of the sequence of moves" -msgstr "" +msgstr "Идите на претходни знак (или на крај) у низу потеза" #: ../pybiklib/ui/main.py:224 msgid "Add Mark" @@ -368,7 +370,7 @@ #: ../pybiklib/ui/main.py:225 msgid "Mark the current place in the sequence of moves" -msgstr "" +msgstr "Забележите овај потез у низ потеза" #: ../pybiklib/ui/main.py:226 msgid "Remove Mark" @@ -376,7 +378,7 @@ #: ../pybiklib/ui/main.py:227 msgid "Remove the mark at the current place in the sequence of moves" -msgstr "" +msgstr "Уклоните знак на текућем месту у низу потеза" #: ../pybiklib/ui/main.py:228 msgid "&Edit Bar" @@ -400,7 +402,7 @@ #: ../pybiklib/ui/preferences.py:252 msgid "Preferences" -msgstr "" +msgstr "Поставке" #: ../pybiklib/ui/preferences.py:253 msgid "Animation Speed:" @@ -408,7 +410,7 @@ #: ../pybiklib/ui/preferences.py:254 msgid "Lighting" -msgstr "" +msgstr "Осветљавање" #: ../pybiklib/ui/preferences.py:255 msgid "Mirror Distance:" @@ -438,7 +440,7 @@ #: ../pybiklib/ui/preferences.py:261 msgid "Four directions" -msgstr "" +msgstr "Четири смера" #: ../pybiklib/ui/preferences.py:262 msgid "" @@ -448,7 +450,7 @@ #: ../pybiklib/ui/preferences.py:263 msgid "Mouse" -msgstr "" +msgstr "Миш" #: ../pybiklib/ui/preferences.py:264 ../pybiklib/ui/preferences.py:265 msgid "Add" @@ -468,11 +470,11 @@ #: ../pybiklib/ui/preferences.py:271 msgid "Color:" -msgstr "" +msgstr "Боја:" #: ../pybiklib/ui/preferences.py:272 msgid "Image File:" -msgstr "" +msgstr "Датотека слике:" #: ../pybiklib/ui/preferences.py:273 msgid "Tiled" @@ -484,7 +486,7 @@ #: ../pybiklib/ui/preferences.py:275 msgid "Background:" -msgstr "" +msgstr "Позадина:" #: ../pybiklib/ui/preferences.py:276 msgid "Appearance" @@ -582,7 +584,7 @@ #: ../data/plugins/20-2x2x2.algorithm.py:41 #: ../data/plugins/20-2x2x2.algorithm.py:61 msgid "Solvers" -msgstr "" +msgstr "Решавачи" #. Spiegel is the name of a solution method #: ../data/plugins/10-spiegel.algorithm.py:37 @@ -594,51 +596,51 @@ #: ../data/plugins/10-spiegel.algorithm.py:134 #: ../data/plugins/10-spiegel.algorithm.py:145 msgid "Spiegel" -msgstr "" +msgstr "Шпигел" #: ../data/plugins/10-spiegel.algorithm.py:40 #: ../data/plugins/11-spiegel-improved.algorithm.py:40 #: ../data/plugins/12-lbl-leyan.algorithm.py:27 msgid "Top edges" -msgstr "" +msgstr "Горње ивице" #: ../data/plugins/10-spiegel.algorithm.py:69 #: ../data/plugins/11-spiegel-improved.algorithm.py:85 #: ../data/plugins/12-lbl-leyan.algorithm.py:56 msgid "Top corners" -msgstr "" +msgstr "Горњи углови" #: ../data/plugins/10-spiegel.algorithm.py:90 #: ../data/plugins/11-spiegel-improved.algorithm.py:124 #: ../data/plugins/12-lbl-leyan.algorithm.py:77 msgid "Middle slice" -msgstr "" +msgstr "Средњи прстен" #: ../data/plugins/10-spiegel.algorithm.py:105 #: ../data/plugins/11-spiegel-improved.algorithm.py:156 #: ../data/plugins/12-lbl-leyan.algorithm.py:173 msgid "Bottom edge place" -msgstr "" +msgstr "Место доње ивице" #: ../data/plugins/10-spiegel.algorithm.py:118 #: ../data/plugins/11-spiegel-improved.algorithm.py:182 #: ../data/plugins/12-lbl-leyan.algorithm.py:93 msgid "Bottom edge orient" -msgstr "" +msgstr "Оријентир доње ивице" #: ../data/plugins/10-spiegel.algorithm.py:135 #: ../data/plugins/11-spiegel-improved.algorithm.py:200 #: ../data/plugins/12-lbl-leyan.algorithm.py:110 #: ../data/plugins/20-2x2x2.algorithm.py:43 msgid "Bottom corner place" -msgstr "" +msgstr "Место доњег угла" #: ../data/plugins/10-spiegel.algorithm.py:146 #: ../data/plugins/11-spiegel-improved.algorithm.py:214 #: ../data/plugins/12-lbl-leyan.algorithm.py:132 #: ../data/plugins/20-2x2x2.algorithm.py:63 msgid "Bottom corner orient" -msgstr "" +msgstr "Оријентир доњег угла" #. Spiegel is the name of a solution method #: ../data/plugins/11-spiegel-improved.algorithm.py:37 @@ -650,7 +652,7 @@ #: ../data/plugins/11-spiegel-improved.algorithm.py:199 #: ../data/plugins/11-spiegel-improved.algorithm.py:213 msgid "Spiegel improved" -msgstr "" +msgstr "Побољшани шпигел" #. Leyan Lo is the inventor of the solution method #: ../data/plugins/12-lbl-leyan.algorithm.py:24 @@ -669,11 +671,11 @@ #: ../data/plugins/20-2x2x2.algorithm.py:42 #: ../data/plugins/20-2x2x2.algorithm.py:62 msgid "2×2×2" -msgstr "" +msgstr "2×2×2" #: ../data/plugins/20-2x2x2.algorithm.py:24 msgid "Top slice" -msgstr "" +msgstr "Горњи прстен" #: ../data/plugins/80-pretty-patterns.algorithm.py:18 #: ../data/plugins/80-pretty-patterns.algorithm.py:22 @@ -706,7 +708,7 @@ #: ../data/plugins/80-pretty-patterns.algorithm.py:136 #: ../data/plugins/80-pretty-patterns.algorithm.py:140 msgid "Pretty patterns" -msgstr "" +msgstr "Занимљиви обрасци" #: ../data/plugins/80-pretty-patterns.algorithm.py:19 #: ../data/plugins/80-pretty-patterns.algorithm.py:23 @@ -716,16 +718,16 @@ #: ../data/plugins/80-pretty-patterns.algorithm.py:40 #: ../data/plugins/80-pretty-patterns.algorithm.py:44 msgid "Stripes" -msgstr "" +msgstr "Траке" #: ../data/plugins/80-pretty-patterns.algorithm.py:49 #: ../data/plugins/80-pretty-patterns.algorithm.py:53 msgid "Criss-Cross" -msgstr "" +msgstr "Унакрсно" #: ../data/plugins/80-pretty-patterns.algorithm.py:57 msgid "Fried Eggs" -msgstr "" +msgstr "Пржена јаја" #: ../data/plugins/80-pretty-patterns.algorithm.py:61 msgid "Big Fried Eggs" @@ -733,7 +735,7 @@ #: ../data/plugins/80-pretty-patterns.algorithm.py:65 msgid "4 Fried Eggs" -msgstr "" +msgstr "4 пржених јаја" #: ../data/plugins/80-pretty-patterns.algorithm.py:69 msgid "Chessboard" @@ -745,7 +747,7 @@ #: ../data/plugins/80-pretty-patterns.algorithm.py:79 msgid "Zig Zag" -msgstr "" +msgstr "Цик-цак" #. T is the shape formed by the cube labels #: ../data/plugins/80-pretty-patterns.algorithm.py:85 @@ -755,7 +757,7 @@ #: ../data/plugins/80-pretty-patterns.algorithm.py:100 #: ../data/plugins/80-pretty-patterns.algorithm.py:104 msgid "T-Time" -msgstr "" +msgstr "Т време" #. C is the shape formed by the cube labels #: ../data/plugins/80-pretty-patterns.algorithm.py:110 diff -Nru pybik-1.0.2~alpha1~bzr1545/po/uk.po pybik-1.0.2~alpha1~bzr1549/po/uk.po --- pybik-1.0.2~alpha1~bzr1545/po/uk.po 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/po/uk.po 2013-02-28 16:46:46.000000000 +0000 @@ -12,14 +12,14 @@ "PO-Revision-Date: 2012-12-15 08:39+0000\n" "Last-Translator: Yuri Chornoivan \n" "Language-Team: Ukrainian \n" +"Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Launchpad-Export-Date: 2012-12-16 04:59+0000\n" -"X-Generator: Launchpad (build 16372)\n" -"Language: uk\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Launchpad-Export-Date: 2013-02-01 04:51+0000\n" +"X-Generator: Launchpad (build 16455)\n" #: ../pybiklib/application.py:304 msgid "Press the Esc key to exit Edit Mode" @@ -122,22 +122,20 @@ msgstr "" "Якщо вами буде виявлено вади у Pybik або у вас виникнуть пропозиції щодо її " "покращення, будь ласка, створіть відповідний <{CONTACT_FILEBUG}|>звіт щодо " -"вади<|>. У останньому випадку позначте звіт щодо вади міткою «Wishlist» " -"(«побажання»)." +"вади<|>. У останньому випадку позначте звіт щодо вади міткою " +"«Wishlist» («побажання»)." #: ../pybiklib/config.py:94 msgid "" -"Translations are managed by the " -"Launchpad " -"translation group<|>.\n" +"Translations are managed by the Launchpad translation group<|>.\n" "\n" "If you want help to translate Pybik to your language you can do it through " "the web interface<|>.\n" "\n" "Read more about \"Translating with " -"Launchpad\"<|> and " -"\"Starting to " -"translate\"<|>." +"Launchpad\"<|> and \"Starting to translate\"<|>." msgstr "" "Переклади виконуються групою перекладачів Launchpad<|>.\n" @@ -145,11 +143,9 @@ "Якщо ви хочете допомогти перекласти Pybik вашою мовою, скористайтеся " "відповідним інтерфейсом<|>.\n" "\n" -"Ознайомтеся з настановами щодо " -"перекладу за допомогою " -"Launchpad<|> та " -"початкових " -"кроків з перекладу<|>." +"Ознайомтеся з настановами щодо перекладу за допомогою Launchpad<|> та початкових кроків з перекладу<|>." #: ../pybiklib/dialogs.py:168 msgid "Press a key …" diff -Nru pybik-1.0.2~alpha1~bzr1545/pybiklib/application.py pybik-1.0.2~alpha1~bzr1549/pybiklib/application.py --- pybik-1.0.2~alpha1~bzr1545/pybiklib/application.py 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/pybiklib/application.py 2013-02-28 16:46:46.000000000 +0000 @@ -1,7 +1,7 @@ #-*- coding:utf-8 -*- # Pybik -- A 3 dimensional magic cube game. -# Copyright © 2009-2012 B. Clausius +# Copyright © 2009-2013 B. Clausius # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -155,10 +155,12 @@ # actions that belongs to no widget self.action_jump_to_editbar = QAction(self) + self.action_jump_to_editbar.setObjectName('action_jump_to_editbar') self.action_jump_to_editbar.setShortcut(QKeySequence(settings.action.edit_moves)) self.action_jump_to_editbar.triggered.connect(self.on_action_jump_to_editbar_triggered) self.addAction(self.action_jump_to_editbar) self.action_edit_model = QAction(self) + self.action_edit_model.setObjectName('action_edit_model') self.action_edit_model.setShortcut(QKeySequence(settings.action.edit_model)) self.action_edit_model.triggered.connect(self.on_action_edit_model_triggered) self.addAction(self.action_edit_model) @@ -199,6 +201,7 @@ def create_cube_area(self): cube_area = drawingarea.CubeArea() + cube_area.setObjectName('drawingarea') sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) diff -Nru pybik-1.0.2~alpha1~bzr1545/pybiklib/debug.py pybik-1.0.2~alpha1~bzr1549/pybiklib/debug.py --- pybik-1.0.2~alpha1~bzr1545/pybiklib/debug.py 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/pybiklib/debug.py 2013-02-28 16:46:46.000000000 +0000 @@ -23,7 +23,7 @@ DEBUG = False DEBUG_FUNC = DEBUG_MSG = DEBUG_RAND = DEBUG_ROTATE = False -DEBUG_DRAW = DEBUG_KEYS = DEBUG_TEST = DEBUG_PICK = False +DEBUG_DRAW = DEBUG_KEYS = DEBUG_PICK = False DEBUG_FPS = DEBUG_VFPS = DEBUG_NOLABEL = DEBUG_NOBEVEL = DEBUG_INNER = False DEBUG_ALG = False diff -Nru pybik-1.0.2~alpha1~bzr1545/pybiklib/main.py pybik-1.0.2~alpha1~bzr1549/pybiklib/main.py --- pybik-1.0.2~alpha1~bzr1545/pybiklib/main.py 2013-02-18 03:54:21.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/pybiklib/main.py 2013-02-28 16:46:46.000000000 +0000 @@ -82,6 +82,16 @@ print(config.wrap(config.LICENSE_NOT_FOUND)) sys.exit(0) +def print_tests(*args): + from pybiktest.testrunner import TestRunner + for filename in TestRunner.get_testdatafiles(): + print(filename) + sys.exit(0) + +def select_all_tests(value, opts): + from pybiktest.testrunner import TestRunner + opts.setdefault('test', []).extend(TestRunner.get_testdatafiles()) + debug_level_names = [__a[6:].lower() for __a in debug.__all__ if __a.startswith('DEBUG_')] arg_info = [ @@ -105,6 +115,12 @@ ' first imports PySide and if that fails it imports PyQt4'), (['--pure-python'], lambda value, opts: opts.setdefault('pure-python', True), 'Use python module for rendering (very slow)'), + (['--list-tests'], print_tests, + 'List tests'), + (['--test'], select_all_tests, + 'Run all tests'), + (['--test='], lambda value, opts: opts.setdefault('test', []).append(value), + 'Run test T, can be used multiple times'), (['--debug='], lambda value, opts: opts.setdefault('debug', value), 'Enable debug output, D is a comma-separated list of debug flags:\n{0}' .format(' '.join(debug_level_names))), @@ -126,7 +142,7 @@ def parse_args(args): arg_functs = {o: f for opts, f, h in arg_info for o in opts or [] if f is not None} opts = {} - ui_args = [] + opts['ui_args'] = ui_args = [] for arg in args: try: index = arg.index('=') @@ -146,12 +162,14 @@ print('You cannot use both --pyside and --pyqt4') sys.exit(1) else: - pythonqt = 'pyside' + opts['pythonqt'] = 'pyside' + del opts['pyside'] else: if 'pyqt4' in opts: - pythonqt = 'pyqt4' + opts['pythonqt'] = 'pyqt4' + del opts['pyqt4'] else: - pythonqt = None + opts['pythonqt'] = None debug_flags = opts.get('debug', None) if debug_flags is not None: @@ -160,10 +178,16 @@ if d not in debug_level_names: print('unknown debug option:', d) sys.exit(1) + del opts['debug'] + opts['debug_flags'] = debug_flags - Opts = namedtuple('Opts', 'debug_flags pythonqt pure_python ui_args config_file defaultconfig') - return Opts(debug_flags, pythonqt, opts.get('pure-python', False), ui_args, - opts.get('config-file', config.USER_SETTINGS_FILE), opts.get('defaultconfig', False)) + opts.setdefault('pure-python', False) + opts.setdefault('config-file', config.USER_SETTINGS_FILE) + opts.setdefault('defaultconfig', False) + class Opts: pass + for k, v in opts.items(): + setattr(Opts, k.replace('-', '_'), v) + return Opts def import_ext(pythonqt, pure_python): if pythonqt != 'pyqt4': @@ -238,9 +262,9 @@ sys.exit(1) -def run_app(root_dir, args, config_file): +def create_app(root_dir, args): import gettext - from PySide.QtCore import QLocale, QTranslator, QTimer + from PySide.QtCore import QLocale, QTranslator from PySide.QtGui import QApplication, QPalette, QColor # initialize QApplication @@ -278,7 +302,9 @@ LOCALEDIR = config.LOCALE_DIR t = gettext.translation(config.PACKAGE, LOCALEDIR, languages=[language], fallback=True) t.install(unicode=True, names=['ngettext']) + return app +def create_window(app, config_file): # initialize settings from .settings import settings try: @@ -288,15 +314,13 @@ '{error_message}').format(error_message=e) debug.debug(error_message) settings.load('') + from PySide.QtCore import QTimer QTimer.singleShot(0, lambda: window.error_dialog(_(error_message))) # create main window # The application module can be imported only if a QApplication object is created from .application import MainWindow - window = MainWindow() - - # run the application - app.exec_() + return MainWindow() def run(root_dir=None): @@ -308,14 +332,27 @@ print('debug flags:', *opts.debug_flags) debug.debug('Qt args:', opts.ui_args) + import_ext(opts.pythonqt, opts.pure_python) + if opts.defaultconfig: + # settings needs Qt, so import_ext must be called before from .settings import settings settings.load('') settings.keystore.dump(sys.stdout, all=True) sys.exit(0) - import_ext(opts.pythonqt, opts.pure_python) - - run_app(root_dir, opts.ui_args, opts.config_file) + app = create_app(root_dir, opts.ui_args) + if opts.test: + from pybiktest.testrunner import TestRunner + for test in opts.test: + if os.path.exists(TestRunner.settings_file): + os.remove(TestRunner.settings_file) + window = create_window(app, TestRunner.settings_file) + TestRunner.start(window, test) + app.exec_() + TestRunner.stop() + else: + window = create_window(app, opts.config_file) + app.exec_() diff -Nru pybik-1.0.2~alpha1~bzr1545/pybiktest/data/general pybik-1.0.2~alpha1~bzr1549/pybiktest/data/general --- pybik-1.0.2~alpha1~bzr1545/pybiktest/data/general 1970-01-01 00:00:00.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/pybiktest/data/general 2013-02-28 16:46:46.000000000 +0000 @@ -0,0 +1,306 @@ +Fields: + edit_text = ['', 'f', 'f ', 'f-', 'f- ', 'l', 'l ', 'l-', 'l- ', 'u', 'u ', 'u-', 'u- '] + edit_pos = [0, 1, 2, 3] + game_len = [0, 1] +Conditions: + edit_pos <= len(edit_text) + edit_pos == len(edit_text) or edit_text[edit_pos] not in '- ' + len(edit_text.replace(' ','').replace('-','')) == game_len +Transition: action_add_mark + State: edit_text='', edit_pos=0 + State: edit_text='f', edit_pos=0 + State: edit_text='f', edit_pos=1 + edit_text='f ', edit_pos=2 + State: edit_text='f ', edit_pos=0 + State: edit_text='f ', edit_pos=2 + State: edit_text='f-', edit_pos=0 + State: edit_text='f-', edit_pos=2 + edit_text='f- ', edit_pos=3 + State: edit_text='f- ', edit_pos=0 + State: edit_text='f- ', edit_pos=3 + State: edit_text='l', edit_pos=0 + State: edit_text='l', edit_pos=1 + edit_text='l ', edit_pos=2 + State: edit_text='l ', edit_pos=0 + State: edit_text='l ', edit_pos=2 + State: edit_text='l-', edit_pos=0 + State: edit_text='l-', edit_pos=2 + edit_text='l- ', edit_pos=3 + State: edit_text='l- ', edit_pos=0 + State: edit_text='l- ', edit_pos=3 + State: edit_text='u', edit_pos=0 + State: edit_text='u', edit_pos=1 + edit_text='u ', edit_pos=2 + State: edit_text='u ', edit_pos=0 + State: edit_text='u ', edit_pos=2 + State: edit_text='u-', edit_pos=0 + State: edit_text='u-', edit_pos=2 + edit_text='u- ', edit_pos=3 + State: edit_text='u- ', edit_pos=0 + State: edit_text='u- ', edit_pos=3 +Transition: action_forward + State: edit_text='', edit_pos=0 + State: edit_text='f', edit_pos=0 + edit_pos=1 + State: edit_text='f', edit_pos=1 + State: edit_text='f ', edit_pos=0 + edit_pos=2 + State: edit_text='f ', edit_pos=2 + State: edit_text='f-', edit_pos=0 + edit_pos=2 + State: edit_text='f-', edit_pos=2 + State: edit_text='f- ', edit_pos=0 + edit_pos=3 + State: edit_text='f- ', edit_pos=3 + State: edit_text='l', edit_pos=0 + edit_pos=1 + State: edit_text='l', edit_pos=1 + State: edit_text='l ', edit_pos=0 + edit_pos=2 + State: edit_text='l ', edit_pos=2 + State: edit_text='l-', edit_pos=0 + edit_pos=2 + State: edit_text='l-', edit_pos=2 + State: edit_text='l- ', edit_pos=0 + edit_pos=3 + State: edit_text='l- ', edit_pos=3 + State: edit_text='u', edit_pos=0 + edit_pos=1 + State: edit_text='u', edit_pos=1 + State: edit_text='u ', edit_pos=0 + edit_pos=2 + State: edit_text='u ', edit_pos=2 + State: edit_text='u-', edit_pos=0 + edit_pos=2 + State: edit_text='u-', edit_pos=2 + State: edit_text='u- ', edit_pos=0 + edit_pos=3 + State: edit_text='u- ', edit_pos=3 +Transition: action_initial_state + State: edit_text='', edit_pos=0, game_len=0 + State: edit_text='f', edit_pos=0, game_len=1 + State: edit_text='f', edit_pos=1, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='f ', edit_pos=0, game_len=1 + State: edit_text='f ', edit_pos=2, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='f-', edit_pos=0, game_len=1 + State: edit_text='f-', edit_pos=2, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='f- ', edit_pos=0, game_len=1 + State: edit_text='f- ', edit_pos=3, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='l', edit_pos=0, game_len=1 + State: edit_text='l', edit_pos=1, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='l ', edit_pos=0, game_len=1 + State: edit_text='l ', edit_pos=2, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='l-', edit_pos=0, game_len=1 + State: edit_text='l-', edit_pos=2, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='l- ', edit_pos=0, game_len=1 + State: edit_text='l- ', edit_pos=3, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='u', edit_pos=0, game_len=1 + State: edit_text='u', edit_pos=1, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='u ', edit_pos=0, game_len=1 + State: edit_text='u ', edit_pos=2, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='u-', edit_pos=0, game_len=1 + State: edit_text='u-', edit_pos=2, game_len=1 + edit_text='', edit_pos=0, game_len=0 + State: edit_text='u- ', edit_pos=0, game_len=1 + State: edit_text='u- ', edit_pos=3, game_len=1 + edit_text='', edit_pos=0, game_len=0 +Transition: action_invert_moves + State: edit_text='', edit_pos=0 + State: edit_text='f', edit_pos=0 + edit_text='f-' + State: edit_text='f', edit_pos=1 + edit_text='f-', edit_pos=2 + State: edit_text='f ', edit_pos=0 + edit_text='f-' + State: edit_text='f ', edit_pos=2 + edit_text='f-' + State: edit_text='f-', edit_pos=0 + edit_text='f' + State: edit_text='f-', edit_pos=2 + edit_text='f', edit_pos=1 + State: edit_text='f- ', edit_pos=0 + edit_text='f' + State: edit_text='f- ', edit_pos=3 + edit_text='f', edit_pos=1 + State: edit_text='l', edit_pos=0 + edit_text='l-' + State: edit_text='l', edit_pos=1 + edit_text='l-', edit_pos=2 + State: edit_text='l ', edit_pos=0 + edit_text='l-' + State: edit_text='l ', edit_pos=2 + edit_text='l-' + State: edit_text='l-', edit_pos=0 + edit_text='l' + State: edit_text='l-', edit_pos=2 + edit_text='l', edit_pos=1 + State: edit_text='l- ', edit_pos=0 + edit_text='l' + State: edit_text='l- ', edit_pos=3 + edit_text='l', edit_pos=1 + State: edit_text='u', edit_pos=0 + edit_text='u-' + State: edit_text='u', edit_pos=1 + edit_text='u-', edit_pos=2 + State: edit_text='u ', edit_pos=0 + edit_text='u-' + State: edit_text='u ', edit_pos=2 + edit_text='u-' + State: edit_text='u-', edit_pos=0 + edit_text='u' + State: edit_text='u-', edit_pos=2 + edit_text='u', edit_pos=1 + State: edit_text='u- ', edit_pos=0 + edit_text='u' + State: edit_text='u- ', edit_pos=3 + edit_text='u', edit_pos=1 +Transition: action_jump_to_editbar + State: +Transition: action_new + State: + edit_text='', edit_pos=0, game_len=0 +Transition: action_new_solved + State: + edit_text='', edit_pos=0, game_len=0 +Transition: action_next + State: edit_text='', edit_pos=0 + State: edit_text='f', edit_pos=0 + edit_pos=1 + State: edit_text='f', edit_pos=1 + State: edit_text='f ', edit_pos=0 + edit_pos=2 + State: edit_text='f ', edit_pos=2 + State: edit_text='f-', edit_pos=0 + edit_pos=2 + State: edit_text='f-', edit_pos=2 + State: edit_text='f- ', edit_pos=0 + edit_pos=3 + State: edit_text='f- ', edit_pos=3 + State: edit_text='l', edit_pos=0 + edit_pos=1 + State: edit_text='l', edit_pos=1 + State: edit_text='l ', edit_pos=0 + edit_pos=2 + State: edit_text='l ', edit_pos=2 + State: edit_text='l-', edit_pos=0 + edit_pos=2 + State: edit_text='l-', edit_pos=2 + State: edit_text='l- ', edit_pos=0 + edit_pos=3 + State: edit_text='l- ', edit_pos=3 + State: edit_text='u', edit_pos=0 + edit_pos=1 + State: edit_text='u', edit_pos=1 + State: edit_text='u ', edit_pos=0 + edit_pos=2 + State: edit_text='u ', edit_pos=2 + State: edit_text='u-', edit_pos=0 + edit_pos=2 + State: edit_text='u-', edit_pos=2 + State: edit_text='u- ', edit_pos=0 + edit_pos=3 + State: edit_text='u- ', edit_pos=3 +Transition: action_normalize_complete_rotations + State: +Transition: action_play + State: edit_text='', edit_pos=0 + State: edit_text='f', edit_pos=0 + edit_pos=1 + State: edit_text='f', edit_pos=1 + State: edit_text='f ', edit_pos=0 + edit_pos=2 + State: edit_text='f ', edit_pos=2 + State: edit_text='f-', edit_pos=0 + edit_pos=2 + State: edit_text='f-', edit_pos=2 + State: edit_text='f- ', edit_pos=0 + edit_pos=3 + State: edit_text='f- ', edit_pos=3 + State: edit_text='l', edit_pos=0 + edit_pos=1 + State: edit_text='l', edit_pos=1 + State: edit_text='l ', edit_pos=0 + edit_pos=2 + State: edit_text='l ', edit_pos=2 + State: edit_text='l-', edit_pos=0 + edit_pos=2 + State: edit_text='l-', edit_pos=2 + State: edit_text='l- ', edit_pos=0 + edit_pos=3 + State: edit_text='l- ', edit_pos=3 + State: edit_text='u', edit_pos=0 + edit_pos=1 + State: edit_text='u', edit_pos=1 + State: edit_text='u ', edit_pos=0 + edit_pos=2 + State: edit_text='u ', edit_pos=2 + State: edit_text='u-', edit_pos=0 + edit_pos=2 + State: edit_text='u-', edit_pos=2 + State: edit_text='u- ', edit_pos=0 + edit_pos=3 + State: edit_text='u- ', edit_pos=3 +Transition: action_previous + State: + edit_pos=0 +Transition: action_remove_mark + State: edit_text='', edit_pos=0 + State: edit_text='f', edit_pos=0 + State: edit_text='f', edit_pos=1 + State: edit_text='f ', edit_pos=0 + State: edit_text='f ', edit_pos=2 + edit_text='f', edit_pos=1 + State: edit_text='f-', edit_pos=0 + State: edit_text='f-', edit_pos=2 + State: edit_text='f- ', edit_pos=0 + State: edit_text='f- ', edit_pos=3 + edit_text='f-', edit_pos=2 + State: edit_text='l', edit_pos=0 + State: edit_text='l', edit_pos=1 + State: edit_text='l ', edit_pos=0 + State: edit_text='l ', edit_pos=2 + edit_text='l', edit_pos=1 + State: edit_text='l-', edit_pos=0 + State: edit_text='l-', edit_pos=2 + State: edit_text='l- ', edit_pos=0 + State: edit_text='l- ', edit_pos=3 + edit_text='l-', edit_pos=2 + State: edit_text='u', edit_pos=0 + State: edit_text='u', edit_pos=1 + State: edit_text='u ', edit_pos=0 + State: edit_text='u ', edit_pos=2 + edit_text='u', edit_pos=1 + State: edit_text='u-', edit_pos=0 + State: edit_text='u-', edit_pos=2 + State: edit_text='u- ', edit_pos=0 + State: edit_text='u- ', edit_pos=3 + edit_text='u-', edit_pos=2 +Transition: action_reset_rotation + State: +Transition: action_rewind + State: + edit_pos=0 +Transition: action_stop + State: +Transition: edit_moves_empty + State: + edit_text='', edit_pos=0, game_len=0 +Transition: edit_moves_f + State: + edit_text='f', edit_pos=1, game_len=1 +Transition: edit_moves_l + State: + edit_text='l', edit_pos=1, game_len=1 +Transition: edit_moves_u + State: + edit_text='u', edit_pos=1, game_len=1 diff -Nru pybik-1.0.2~alpha1~bzr1545/pybiktest/testrunner.py pybik-1.0.2~alpha1~bzr1549/pybiktest/testrunner.py --- pybik-1.0.2~alpha1~bzr1545/pybiktest/testrunner.py 1970-01-01 00:00:00.000000000 +0000 +++ pybik-1.0.2~alpha1~bzr1549/pybiktest/testrunner.py 2013-02-28 16:46:46.000000000 +0000 @@ -0,0 +1,479 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright © 2013 B. Clausius +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import print_function, division + +import sys, os +import random +from collections import namedtuple, defaultdict, OrderedDict + + +known_fields = 'edit_text edit_pos game_len'.split() +def mkState(fields): + class State(namedtuple('State', fields)): + def tostr(self, other=None): + def field_tostr(i): + if self[i] is matchall: + return '' + elif other is None or self[i] != other[i]: + return '{}={!r}, '.format(self._fields[i], self[i]) + else: + return ' ' * (len(self._fields[i]) + len(repr(self[i])) + 3) + return ''.join([field_tostr(i) for i in range(len(self))]).rstrip(', ') + + def asdict(self, fields): + res = self._asdict() + for field in res.keys(): + if field not in fields: + del res[field] + return res + + default = staticmethod(lambda: State(**{f: matchall for f in State._fields})) + return State + + +class Result (OrderedDict): + __slots__ = () + + no_error = set() + + def __init__(self): + OrderedDict.__init__(self) + + errors = property(lambda self: sum(v for k, v in self.items() if k not in self.no_error)) + + def __str__(self): + return ', '.join('{0}: {{0.{0}}}'.format(s) for s in self.keys()).format(self) + + def __getattr__(self, key): + if key.startswith('_'): + raise AttributeError() + return self.setdefault(key, 0) + + def __setattr__(self, key, value): + if key.startswith('_') or key in self.__dict__.keys(): + OrderedDict.__setattr__(self, key, value) + else: + self[key] = value + + +class Quit (Exception): pass +class MatchAll (object): pass +matchall = MatchAll() + + +class WidgetTransitions (object): + def _make_edit_moves_set_text(text): + def _edit_moves_set_text(widget): + widget.setText(text) + widget.returnPressed.emit() + return _edit_moves_set_text + edit_moves_empty = _make_edit_moves_set_text('') + edit_moves_f = _make_edit_moves_set_text('f') + edit_moves_l = _make_edit_moves_set_text('l') + edit_moves_u = _make_edit_moves_set_text('u') + + +class TestRunner (object): + _instance = None + settings_file = 'pybiktest/settings.conf' + test_dir = 'pybiktest/data' + + @classmethod + def get_testdatafiles(cls): + return [f for f in os.listdir(cls.test_dir) if not f.endswith('~')] + + def __init__(self, main_window, test): + assert self._instance is None + self.main_window = main_window + self.current_test = os.path.join(self.test_dir, test) + self.transitions = {} + self.widgets = {} + self.fields = OrderedDict() + self.conditions = [] + self.result = Result() + self.running = True + + from pybiklib.settings import settings + settings.draw.speed = 120 + + from PySide.QtCore import QTimer + self.timer = QTimer() + loop_iter = self.loop() + self.timer.timeout.connect(lambda: next(loop_iter)) + self.timer.start(10) + + def isvalid(self, state): + state = state.asdict(self.fields) + for condition in self.conditions[:]: + try: + if not eval(condition, state): + return False + except Exception as e: + print('Error in condition:', e) + self.result.condition_error += 1 + self.conditions.remove(condition) + return True + + def read_test(self): + def parse_fields(line): + assert self.fields == {} + if line != 'Fields:\n': + for f in known_fields: + self.fields[f] = [] + return parse_conditions, line, [] + return parse_field, None, [] + def parse_field(line): + if not line.startswith(' '): + return parse_conditions, line, [] + field, value = line.split('=', 1) + field = field.strip() + value = eval(value) + self.fields[field] = value + return parse_field, None, [] + def parse_conditions(line): + self.State = mkState(self.fields) + if line != 'Conditions:\n': + return parse_transition, line, [] + return parse_condition, None, [] + def parse_condition(line): + if not line.startswith(' '): + return parse_transition, line, [] + self.conditions.append(line.strip()) + return parse_condition, None, [] + def parse_transition(line): + if not line.startswith('Transition:'): + return parse_unknown, line, ['transition'] + name = line.split(':', 1)[1].strip() + states = {} + if name in self.transitions: + print('Duplicate transition: %r' % name) + self.result.duplicate_a += 1 + else: + self.transitions[name] = None, states + return parse_state1, None, [states] + def _parse_state_value(default, state): + try: + state = eval('dict({})'.format(state)) + except SyntaxError: + print('Error parsing state: %r' % state) + self.result.parse_error += 1 + state = None + else: + for field in state.keys(): + if field not in self.fields: + print('Unselected field:', field) + self.result.unselected_f += 1 + del state[field] + state = default and default._replace(**state) + return state + def parse_state1(line, states): + if not line.startswith(' State:'): + return parse_transition, line, [] + line = line.split(':', 1)[1].strip() + state = _parse_state_value(self.State.default(), line) + return parse_state2, None, [states, state] + def expand_state(fields, state, target, i=0): + if state is None or target is None: + return + if i >= len(fields): + yield state, target + return + field, values = fields[i] + if getattr(state, field) is matchall: + for value in values: + rstate = state._replace(**{field: value}) + if getattr(target, field) is matchall: + rtarget = target._replace(**{field: value}) + else: + rtarget = target + for estate, etarget in expand_state(fields, rstate, rtarget, i+1): + yield estate, etarget + else: + for estate, etarget in expand_state(fields, state, target, i+1): + yield estate, etarget + def parse_state2(line, states, state): + if not line.startswith(' '): + target = state + else: + target = _parse_state_value(state, line.strip()) + line = None + for state, target in expand_state(self.fields.items(), state, target): + if state in states: + print('duplicate state:', state.tostr()) + self.result.duplicate_s += 1 + elif self.isvalid(state): + assert self.isvalid(target) + states[state] = target + return parse_state1, line, [states] + def parse_unknown(line, src): + if line == 'End.' or src == 'end': + return parse_unknown, None, ['end'] + print('Error parsing {}: {!r}'.format(src, line)) + self.result.parse_error += 1 + return parse_transition, None, [] + + def process_line(func, line, *args): + while line is not None: + func, line, args = func(line, *args) + return func, args + + with open(self.current_test, 'rt') as testfile: + func = parse_fields + args = [] + for line in testfile: + func, args = process_line(func, line, *args) + process_line(func, 'End.', *args) + + def _ignore_fields(self, states, igntype): + result = {} + for i, field in enumerate(self.State._fields): + target_value = matchall + for state, target in states.items(): + if igntype == 'unchanged' and state[i] != target[i]: + result = {} + break + else: + if igntype == 'unchanged': + state = state._replace(**{field: matchall}) + target = target._replace(**{field: matchall}) + else: + assert igntype == 'sametarget' + if target_value in {matchall, target[i]}: + state = state._replace(**{field: matchall}) + target_value = target[i] + else: + result = {} + break + if state in result and result[state] != target: + result = {} + break + else: + result[state] = target + else: + states = result + result = {} + return states + + def write_test(self): + with open(self.current_test, 'wt') as testfile: + testfile.write('Fields:\n') + for field, values in self.fields.items(): + print(' ', field, '=', values, file=testfile) + if self.conditions: + testfile.write('Conditions:\n') + for condition in self.conditions: + print(' ', condition, file=testfile) + for name in sorted(self.transitions.keys()): + testfile.write('Transition: %s\n' % name) + unused_func, states = self.transitions[name] + states = self._ignore_fields(states, 'unchanged') + states = self._ignore_fields(states, 'sametarget') + for state, target in sorted(states.items()): + testfile.write(' State: {}\n'.format(state.tostr())) + if state != target: + testfile.write(' {}\n'.format(target.tostr(state))) + + def get_state(self): + edit_moves = self.widgets['edit_moves'] + text = str(edit_moves.text()) + moves = self.main_window.gamestate.all_moves + state = dict(edit_text=text, edit_pos=edit_moves.cursorPosition(), game_len=len(moves.moves)) + state = {k:v for k,v in state.items() if k in self.fields} + return self.State(**state) + + def init_test(self): + try: + self.read_test() + except IOError as e: + print('Error reading test data file:', e) + write_template = False + if not self.transitions: + self.result.empty_test += 1 + write_template = True + + for field in known_fields: + if field not in self.fields: + print('skipping field', field) + # introspect ui + from PySide.QtGui import QAction, QWidget + widgets = [] + for child in self.main_window.children(): + name = child.objectName() + if isinstance(child, QAction): + if name in self.transitions: + func_, states = self.transitions[name] + assert func_ is None + self.transitions[name] = child.trigger, states + elif write_template: + self.transitions[name] = child.trigger, {} + else: + print('skipping action', name) + elif name == 'centralwidget': + widgets.append(child) + def mk_transition(func, widget): + return lambda: func(widget) + for widget in widgets: + for child in widget.children(): + name = child.objectName() + if name and isinstance(child, QWidget): + widgets.append(child) + self.widgets[name] = child + widget_used = False + for fname, func in WidgetTransitions.__dict__.items(): + if not fname.startswith(name): + continue + if fname in self.transitions: + func_, states = self.transitions[fname] + assert func_ is None, (name, fname, func_) + self.transitions[fname] = mk_transition(func, child), states + widget_used = True + elif write_template: + self.transitions[fname] = mk_transition(func, child), {} + widget_used = True + else: + print('skipping widget transition', fname) + if not widget_used and not name.startswith('qt_'): + print('skipping widget', name) + for name, (func, unused_states) in self.transitions.items(): + if func is None: + print('Unknown action:', name) + self.result.unknown_a += 1 + del self.transitions[name] + self.current_state = self.get_state() + self.untested = {self.current_state: self.transitions.keys()} + self.tested_states = defaultdict(int) + if write_template: + raise Quit('end of write template mode') + + def get_random_action(self): + untested = self.untested[self.current_state] + if len(self.tested_states) == len(self.untested): + raise Quit('end of self test.') + if untested: + name = untested.pop(random.randrange(len(untested))) + if not untested: + self.tested_states[self.current_state] += 1 + else: + assert self.current_state in self.tested_states + level = self.tested_states[self.current_state] + for name_, (func_, states_) in self.transitions.items(): + target_ = states_[self.current_state] + if target_ not in self.tested_states or self.tested_states[target_] < level: + name = name_ + break + else: + self.tested_states[self.current_state] += 1 + return + return name + + def do_post_action(self, name, states, target): + current_state = self.get_state() + if target is None: + self.result.unknown += 1 + print('unknown transition:\n {}: {} -> {}'.format( + name, self.current_state.tostr(), current_state.tostr())) + states[self.current_state] = current_state + else: + if target != current_state: + self.result.wrong += 1 + print('wrong target for {}: {}\n found: -> {}\n expected: -> {}'.format( + name, self.current_state.tostr(), current_state.tostr(), target.tostr())) + states[self.current_state] = current_state + if current_state not in self.untested: + self.untested[current_state] = self.transitions.keys() + self.current_state = current_state + + def loop(self): + try: + self.current_state = name = target = None # for except statement + self.init_test() + yield + while True: + name = None + while name is None: + name = self.get_random_action() + func, states = self.transitions[name] + target = states.get(self.current_state, None) + func() + self.result.visited += 1 + yield + while self.main_window.is_animating(): + yield + self.do_post_action(name, states, target) + except Quit as e: + Result.no_error.update(['visited', 'states', 'transitions']) + all_states = set() + all_transitions = set() + for name, (unused_func, states) in self.transitions.items(): + all_states.update(states.keys()) + all_states.update(states.values()) + all_transitions.update((name, state) for state in states.keys()) + self.result.states = len(all_states) + self.result.transitions = len(all_transitions) + unreached = all_states.difference(set(self.untested.keys())) + if unreached: + self.result.unreached = len(unreached) + for state in unreached: + print('unreached:', state.tostr()) + print('Result:', self.result) + if self.result.errors: + field_values = {} + for name, (unused_func, states) in self.transitions.items(): + for state, target in states.items(): + if state in unreached: + del states[state] + continue + for field, svalue, tvalue in zip(self.State._fields, state, target): + field_values.setdefault(field, set()).update([svalue, tvalue]) + for field, values in self.fields.items(): + if field in field_values: + if set(values) != field_values[field]: + print('changed field values of', field) + self.result.changed_f += 1 + values[:] = sorted(field_values[field]) + else: + print('unused field', field) + self.result.unused_f += 1 + self.write_test() + print('new transition file written') + print(e) + except Exception: + print('action {}: {} -> {}'.format(name, + self.current_state and self.current_state.tostr(), + target and target.tostr())) + sys.excepthook(*sys.exc_info()) + finally: + self.running = False + self.timer.stop() + self.main_window.close() + yield + + @classmethod + def start(cls, *args): + cls._instance = cls(*args) + + @classmethod + def stop(cls): + if cls._instance is None: + print('No instance for %s, this should not happen.' % cls.__name__) + elif cls._instance.running: + print('Unexpected end of', cls.__name__) + cls._instance = None + +