Whonix Repository GUI Tool (Python)

whonix_repository exit code message is written in real time to stdout.
https://github.com/troubadoour/whonix-repository-wizard/commit/d13ba777d28dda09da38169b983bb08eb964f7b8

Just in case: exit code not zero.
https://github.com/troubadoour/whonix-repository-wizard/commit/da5b74cf50b92c6a78d9176cc103d37db150e665

Works for me.

Added two commits on top:

Added to Whonix/Whonix:
https://github.com/Whonix/Whonix/commit/32c31b8d57ab7edc6fc9444165f6a28a06225568

Removed desktop icon, recommend whonix-repository-wizard:
https://github.com/Whonix/whonix-repository/commit/8430c86df0072d67b0aa1d189fc696d3142a986e
(You need that change, otherwise you cannot install whonix-repository-wizard, because no file may be owned by two packages at once.

Added start menu entry:
https://github.com/Whonix/whonix-repository-wizard/commit/607c87b3352955ea5ae5ea33e11f099fa5604701

There is an issue with the start menu entry. The cursor is bouncing even through it’s already open. There is no launch feedback.

Maybe you got any idea how we could implement launch feedback?

Pushed two commits.
https://github.com/troubadoour/whonix-repository-wizard/commit/e6d210cb51795a3d1b59c23f3160d2fbc0e06d8a
https://github.com/troubadoour/whonix-repository-wizard/commit/1a896bd58fa6819fec200b2008fbed1960035e01

The user text is in “usr/share/whonix/whonix-shared-translations” for not finding a better place-name.

The idea is to put all the GUI text in this file, or at least the text for the initial setup to start with.

There is a change in debian/control in https://github.com/troubadoour/whonix-repository-wizard/commit/e6d210cb51795a3d1b59c23f3160d2fbc0e06d8a. Should have committed separately.

There is an issue with the start menu entry. The cursor is bouncing even through it's already open. There is no launch feedback.

Do you still have this issue? Nothing like that on this side.

Merged. Looks all good.

Few comments.

Is this a usual way to do this in python? Probably best to not invent something here. How do other python projects do this? I am asking, so we don’t get a feature request anytime soon “please do it the standard way, so you could profit from our translation service”. https://translatewiki.net is such a service. Their community translates applications (not wiki websites) for free. Kinda great. And if we go for translations, we should make sure they’d be able to jump in.

I am not sure about a correct path.

Maybe
/usr/(share or lib?)/whonix-repository- wizard/translations
?

Likely, we know more as soon we have an answer for 1).

Do you still have this issue? Nothing like that on this side.[/quote]
It’s fixed. Dunno why. Eventually because of reboot.

There are many formats and ways to write translations. Some use a different file for each language and some combine. The format I implemented was very light compared to the larger projects I have used them for. What we should do is create a dedicated Mixin class adapter that we call and use for all the python modules. That adaptter can then be super classed as well to proved an interface to other services.

Yaml is very flexible and works nicely with python as it translates into dictionaries and lists and is very readable and it is also directly inter-changable with json with one command, which means it can be easily adapted to javascript as well. It would not be difficult to interface with any provider service; all that would need to be done is a small ‘plug-in’ written to interface with some type of api. The most popular configuration type file formats now-a-days are json, yaml, ini and xml. I used to used xml for everything but its not very human friendly but has great validation if you ever need to parse data.

Some translations are based on more than just en, like en_US and en_CA, etc but I figured you would only be needling the base languages. If we create the mixin, then in the future we can change that and only the adapter code needs to be changed.

We can also write a shell interface real easy for the shell scripts.

Now saying all that, there are many translation packages available that would be able to replace this simple one without much effort. Again adapters if used we can adapt it to anything.

And to finally answer your question there is no standard in which internationalization service to use but there are standard on file formats, character encoding, etc. Python implements some internationalization services itself (https://docs.python.org/2/library/gettext.html) but many frameworks implement their own custom implementations, for example Django (https://docs.djangoproject.com/en/dev/topics/i18n/translation/) Some are very complex, some are basic.

You just need to decide on what you want out of the translations as I only saw a handful of items that would need translation and therefore though something together quick. It was a nice way to separate the text out of all the modules and place it all together.

These are the items you should take into consideration:

[ul][li]Ease of use for maintaining translations. I would think you would want a human readable format and that narrows it down to ini or yaml which would allow others to be able to easily provide translations. json is only nice for programmers; not so much for xml.[/li]
[li]How many ‘modules’ will use service? 10, 20, 200?[/li]
[li]Do you want bash shell integration?[/li]
[li]Any other computer languages to interface? Javascript?[/li]
[li]Automatic translation services. Guess we should see what formats they want for translating. Any format is easily deserialized and serialized.[/li]
[li]How many languages you plan on servicing[/li]
[li]How do you want to incorporate the translations. They can be placed in a separate file or files for each language. The can just be written in English in the applications and the translation program will create the appropriate files. For example you can get a package that will allow _(This is a string) and that will end up in a translation file automatically. It can be a pain to change the base code though since you then need to sift though many files[/li][/ul]

Anyway, I’m real tired now and that should give you something to think about. Take a look at the Pyhon API I can you a link to and really think if you need a feature set like that or if something simple like we are using now. Zope also has some stuff to look at.

Sounds good overall.

We’ll figure out what the https://translatewiki.net/ people say as soon someone works on https://github.com/Whonix/Whonix/issues/15.

Do you want bash shell integration?

I don’t know. No strong opinion. We could also go for the usual way to translate the bash scripts. (Similar to Tails.) We’ll figure out once someone starts working on https://github.com/Whonix/Whonix/issues/15.

@nrgaway
I had a quick dive into the code internationalization jungle. Ye there are many ways, but the one you proposed (yaml) seems adapted to the size of the project. I do not believe we’ll ever have many Whonix specific Python GUI scripts. The biggest verbose comes from msgdispatcher_dispatch_x, which displays the cli output from whonixcheck, written in bash.

Realistcally, we are probably left with two maintainable solutions:

  • yaml. Single file , human readable, accepted (preferred) by translatewiki.
  • gettext. Multiple files, human readble, _(‘this is a string’) in the code (easy), .pot format, not straight forward in translatewiki.

I did use xml in Windows (.net). I do not how easy it is to serialize / deserialize in Python, but it’s not a contender for our case. And it does not look very popular in the Linux world.

The others , Babel, Zope and clones are probably too complex.

accepted (preferred) by translatewiki.

Yay! Awesome!

(The following questions are just for better understanding. No need to slow your process down.)

Even if more complex gui tools are added, why would that solution not work?

And even if more complex gui tools are added, who says that for a different package we have to say the same mechanism? :slight_smile:

Even if more complex gui tools are added, why would that solution not work?
It should work. @nrgaway: Do you see reason why it should not?
And even if more complex gui tools are added, who says that for a different package we have to say the same mechanism? :)
I think it could become more a question of file size than complexity.

Let’s say (for the sake of example only!) that we port whonixcheck to Python. Then, because of the size of the text, it could be splitted in multiple files instead of using another option.

I have pushed some commits to GitHub - troubadoour/whonix-repository-wizard. Because there will be some common code, the plan is to complete the exceptions handling before starting whonixsetup-wizard.

Then

We will need it at some stage, so the best is to start now (I’m not familiar with the concept).

Common code as in shared among multiple packages? If that’s the case, whonixsetup-wizard should ideally not depend on whonix-repository-wizard? A shared package as dependency?

It should work.
@nrgaway: Do you see reason why it should not?[/quote]

Can’t see any reason not.

[quote]And even if more complex gui tools are added, who says that for a different package we have to say the same mechanism? :)[/quote] I think it could become more a question of file size than complexity.

Let’s say (for the sake of example only!) that we port whonixcheck to Python. Then, because of the size of the text, it could be splitted in multiple files instead of using another option.

I have pushed some commits to GitHub - troubadoour/whonix-repository-wizard. Because there will be some common code, the plan is to complete the exceptions handling before starting whonixsetup-wizard.

Then

We will need it at some stage, so the best is to start now (I’m not familiar with the concept).

Not much involved in a Mixin. You most likely used them before and maybe never noticed.

So what we need to do is:

[ul][li]Create a separate translation module, maybe called translation.py for example. It is a standalone class capable of getting the translation [/li]
[li]Then in the module that needs access to translations, we just extend the Translation module like class WhonixSetup(Translation) and add a bit of super code in the init to make sure the Translation.init also gets called[/li][/ul]

So what the Mixin does is then provide the extra Translation methods to the class itself instead of needing to instantiate the object like:

from  whonix.translation import Translation

...
t = Translation(lang="en", section="foo", label="setup1")
print t.getTranslation()

we just do this:

from  whonix.translation import Translation

...
class WhonixSetup(QtGui.QMessageBox, Translation):
    def __init__(self, message):
        super(WhonixMessageBox, self).__init__()

    def someMethod(self):
        print self.getTranslation("setup1")

Yeah, you are right, now is the time to make sure we do it all properly!

I can write it over the weekend. All the yaml should be stored in one directory for all modules. Did you decide on the /usr/share/whonix ??

Do you plan on packaging the python modules as an egg or do you plan in installing like script files. I will make the translation module install-able so its available on python path

I figure all the python code should be packaged using proper namespace and shell wrappers to call specific modules which would allow for best option to be able to re-use code among modules. We can use the namespace of whonix; and use the python setup program to install in python path. What are your thoughts?

I guess the other thing to decide would be how to package it all together. Do we want separate packages for each task. like setup and repository or will they be in a shared package. I have not taken the time to think it though yet on what would be best. I’m leaning towards one package though for server, and gateway with a goal to be able to re-use code where possible. We don’t want to run into a maintenance nightmare and if all code is in one code-base it will make it easier for other authors to contribute.

Egg sounds more complicated? Can continue the “simply use deb as a vehicle to drop a file in correct location” approach? Unless there are good arguments for egg? And other packages, that depend on that module just depend on it and import it?

For generic stuff that is not specific to Whonix (and it’s best to keep Whonix specificness to a minimum) please don’t use name spaces named “Whonix”. I’d prefer easier re-usable by anyone names.

For the lib /usr/lib/[?python-transyaml?]/[…]?

For translations /usr/share/whonix-repository-wizard/[…].yaml?

How many packages… We discussed this a bit here:

troubadour wants a separate package of whonixsetup-wizard for Whonix-Gateway and Whonix-Workstation.

What about…

  • whonixsetup - the existing cli tool - as is
  • whonix-repository - the existing cli tool - as is
  • whonix-repository-wizard
  • [?python-transyaml?]/ - the translation lib
  • whonix-gw-setup-wizard
  • whonix-ws-setup-wizard
  • Eventually, if required, whonix-shared-setup-wizard
    ?

What do you think?

[quote=“nrgaway, post:57, topic:635”]Not much involved in a Mixin. You most likely used them before and maybe never noticed.

So what we need to do is:

[ul][li]Create a separate translation module, maybe called translation.py for example. It is a standalone class capable of getting the translation [/li]
[li]Then in the module that needs access to translations, we just extend the Translation module like class WhonixSetup(Translation) and add a bit of super code in the init to make sure the Translation.init also gets called[/li][/ul]

So what the Mixin does is then provide the extra Translation methods to the class itself instead of needing to instantiate the object like:

from  whonix.translation import Translation

...
t = Translation(lang="en", section="foo", label="setup1")
print t.getTranslation()

we just do this:

[code]
from whonix.translation import Translation


class WhonixSetup(QtGui.QMessageBox, Translation):
def init(self, message):
super(WhonixMessageBox, self).init()

def someMethod(self):
    print self.getTranslation("setup1")

[/code][/quote]

After reading some confusing literature about Mixins, I decided to use a more standard approach (that can be changed later).

I created a Translations class (inside the module for the time being) and added the call to it in the Whonix_Repository_Wizard class init(). As a bonus, I have made the yaml parsing “gettext” like.
https://github.com/troubadoour/whonix-repository-wizard/commit/dd3960769e6e60167d44f22feb66c7d1cd38bed6
(There is a couple of commits on top of this one).

I am planning to implement the same in the GUI_message class. The benefit could be that, at the expense of two lines of code per class, I can pass the section I want to use for each new instance of Translations().

Eggs or Wheel are just a standard way of packaging python packages, though are not required. You can still use the Debian packages to distribute and drop the python distrubution in place no matter if its an egg or not.

Ideally any module you want to be able to share code with should be located in one of directories (depending on OS distribution) listed below so its available as an import on python path. You want to just be able to import a module and not have to manually add python paths:

/usr/lib64/python2.7/site-packages
/usr/lib/python2.7/site-packages
For generic stuff that is not specific to Whonix (and it's best to keep Whonix specificness to a minimum) please don't use name spaces named "Whonix". I'd prefer easier re-usable by anyone names.

We could use ‘[font=courier]anon[/font]’ then?

For the lib /usr/lib/[?python-transyaml?]/[...]?

For translations /usr/share/whonix-repository-wizard/[…].yaml?


lib: /usr/lib64/python2.7/site-packages
translations: sounds good

How many packages... We discussed this a bit here: https://www.whonix.org/forum/index.php/topic,705.0.html

troubadour wants a separate package of whonixsetup-wizard for Whonix-Gateway and Whonix-Workstation.

What about…

  • whonixsetup - the existing cli tool - as is
  • whonix-repository - the existing cli tool - as is
  • whonix-repository-wizard
  • [?python-transyaml?]/ - the translation lib
  • whonix-gw-setup-wizard
  • whonix-ws-setup-wizard
  • Eventually, if required, whonix-shared-setup-wizard
    ?

What do you think?

Both the gateway and workstation modules could still be included in the same distribution package as separate modules located on the python path. The benefit of python is that it is object oriented and favours the use of re-use where ever possible. If you have duplicate code, something is wrong; time to refactor :wink: If a module is too long; time to refactor.

Then you just have a shell script that would call it like:

#!/usr/bin/env python
'''
Start Whonix Gateway Wizard.
'''
from anon.gw.setupwizard import setup_main

if __name__ == '__main__':
    setup_main()

This approach keeps all the code together allowing it to be maintained, debugged and tested easily. For debugging, check out WingWare’s integrated IDE and debugger http://wingware.com/. It is one of the most powerful python debuggers out there.

As @troubadour is doing most of the work, I also agree to leave the implementation up to him. Just adding my 2 cents and based on the decisions I will know how to write the translation Mixin.