[PATCHv2] Read /etc/os-release to get product title (#1000426)
Martin Kolman
mkolman at redhat.com
Thu Sep 5 10:56:56 UTC 2013
On Thu, 2013-09-05 at 11:42 +0200, Vratislav Podzimek wrote:
> The /etc/os-release file contains, among the other things, the release name that
> we want to display in the UI.
>
> For GUI we can use just the product title because the string "INITIAL SETUP" is
> shown in the top-left corner. For TUI we should inform user that this is an
> initial setup of the system.
>
> Also rename the hub files not to clash with the the Python package name.
>
> Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
> ---
> initial_setup/gui/gui.py | 13 +++---
> initial_setup/gui/hubs/__init__.py | 2 +-
> initial_setup/gui/hubs/initial_setup.py | 60 ----------------------------
> initial_setup/gui/hubs/initial_setup_hub.py | 60 ++++++++++++++++++++++++++++
> initial_setup/product.py | 34 ++++++++++++++++
> initial_setup/tui/hubs/__init__.py | 2 +-
> initial_setup/tui/hubs/initial_setup.py | 55 --------------------------
> initial_setup/tui/hubs/initial_setup_hub.py | 61 +++++++++++++++++++++++++++++
> initial_setup/tui/tui.py | 13 +++---
> 9 files changed, 167 insertions(+), 133 deletions(-)
> delete mode 100644 initial_setup/gui/hubs/initial_setup.py
> create mode 100644 initial_setup/gui/hubs/initial_setup_hub.py
> create mode 100644 initial_setup/product.py
> delete mode 100644 initial_setup/tui/hubs/initial_setup.py
> create mode 100644 initial_setup/tui/hubs/initial_setup_hub.py
>
> diff --git a/initial_setup/gui/gui.py b/initial_setup/gui/gui.py
> index 24e5a27..3afe5da 100644
> --- a/initial_setup/gui/gui.py
> +++ b/initial_setup/gui/gui.py
> @@ -1,5 +1,5 @@
> from pyanaconda.ui.gui import QuitDialog, GUIObject, GraphicalUserInterface
> -#from .product import productName, productVersion
> +from initial_setup.product import product_title, is_final
> from .hubs import InitialSetupMainHub
> from pyanaconda.ui.gui.spokes import StandaloneSpoke
> import pyanaconda.ui.gui.spokes
> @@ -13,27 +13,24 @@ from di import inject, usesclassinject
> _ = lambda t: t
> N_ = lambda t: t
>
> -productTitle = lambda: "Initial Setup of Fedora"
> -isFinal = lambda: False
> -
> class InitialSetupQuitDialog(QuitDialog):
> MESSAGE = N_("Are you sure you want to quit the configuration process?\n"
> "You might end up with unusable system if you do.")
>
> - at inject(Gdk, productTitle = productTitle, isFinal = isFinal)
> + at inject(Gdk, product_title = product_title, is_final = is_final)
> class InitialSetupGraphicalUserInterface(GraphicalUserInterface):
> """This is the main Gtk based firstboot interface. It inherits from
> anaconda to make the look & feel as similar as possible.
> """
>
> screenshots_directory = "/tmp/initial-setup-screenshots"
> -
> +
> @usesclassinject
> def __init__(self, storage, payload, instclass):
> GraphicalUserInterface.__init__(self, storage, payload, instclass,
> - productTitle, isFinal,
> + product_title, is_final,
> quitDialog = InitialSetupQuitDialog)
> -
> +
> def _list_hubs(self):
> return [InitialSetupMainHub]
>
> diff --git a/initial_setup/gui/hubs/__init__.py b/initial_setup/gui/hubs/__init__.py
> index 5d166d6..39d8b13 100644
> --- a/initial_setup/gui/hubs/__init__.py
> +++ b/initial_setup/gui/hubs/__init__.py
> @@ -1 +1 @@
> -from .initial_setup import InitialSetupMainHub
> +from .initial_setup_hub import InitialSetupMainHub
> diff --git a/initial_setup/gui/hubs/initial_setup.py b/initial_setup/gui/hubs/initial_setup.py
> deleted file mode 100644
> index f966782..0000000
> --- a/initial_setup/gui/hubs/initial_setup.py
> +++ /dev/null
> @@ -1,60 +0,0 @@
> -from pyanaconda.ui.gui.hubs import Hub
> -from pyanaconda.ui.gui.spokes import Spoke
> -from pyanaconda.ui.common import collect
> -import os
> -
> -__all__ = ["InitialSetupMainHub"]
> -
> -def collect_spokes(mask_paths):
> - """Return a list of all spoke subclasses that should appear for a given
> - category. Look for them in files imported as module_path % basename(f)
> -
> - :param mask_paths: list of mask, path tuples to search for classes
> - :type mask_paths: list of (mask, path)
> -
> - :return: list of Spoke classes belonging to category
> - :rtype: list of Spoke classes
> -
> - """
> - spokes = []
> - for mask, path in mask_paths:
> - spokes.extend(collect(mask, path,
> - lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
> -
> - print spokes
> - return spokes
> -
> -
> -class InitialSetupMainHub(Hub):
> - uiFile = "initial_setup.glade"
> - builderObjects = ["summaryWindow"]
> - mainWidgetName = "summaryWindow"
> -
> - def _collectCategoriesAndSpokes(self):
> - """collects categories and spokes to be displayed on this Hub
> -
> - :return: dictionary mapping category class to list of spoke classes
> - :rtype: dictionary[category class] -> [ list of spoke classes ]
> - """
> -
> - ret = {}
> -
> - # Collect all the categories this hub displays, then collect all the
> - # spokes belonging to all those categories.
> - candidate_spokes = collect_spokes(self.paths["spokes"])
> - spokes = [spoke for spoke in candidate_spokes \
> - if spoke.should_run("firstboot", self.data)]
> -
> - for spoke in spokes:
> - ret.setdefault(spoke.category, [])
> - ret[spoke.category].append(spoke)
> -
> - return ret
> -
> - @property
> - def continueButton(self):
> - return self.builder.get_object("continueButton")
> -
> - @property
> - def quitButton(self):
> - return self.builder.get_object("quitButton")
> diff --git a/initial_setup/gui/hubs/initial_setup_hub.py b/initial_setup/gui/hubs/initial_setup_hub.py
> new file mode 100644
> index 0000000..d0ac15b
> --- /dev/null
> +++ b/initial_setup/gui/hubs/initial_setup_hub.py
> @@ -0,0 +1,60 @@
> +from pyanaconda.ui.gui.hubs import Hub
> +from pyanaconda.ui.gui.spokes import Spoke
> +from pyanaconda.ui.common import collect
> +import os
> +
> +__all__ = ["InitialSetupMainHub"]
> +
> +def collect_spokes(mask_paths):
> + """Return a list of all spoke subclasses that should appear for a given
> + category. Look for them in files imported as module_path % basename(f)
> +
> + :param mask_paths: list of mask, path tuples to search for classes
> + :type mask_paths: list of (mask, path)
> +
> + :return: list of Spoke classes belonging to category
> + :rtype: list of Spoke classes
> +
> + """
> + spokes = []
> + for mask, path in mask_paths:
> + spokes.extend(collect(mask, path,
> + lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
> +
> + print spokes
> + return spokes
> +
> +
> +class InitialSetupMainHub(Hub):
> + uiFile = "initial_setup.glade"
> + builderObjects = ["summaryWindow"]
> + mainWidgetName = "summaryWindow"
> +
> + def _collectCategoriesAndSpokes(self):
> + """collects categories and spokes to be displayed on this Hub
> +
> + :return: dictionary mapping category class to list of spoke classes
> + :rtype: dictionary[category class] -> [ list of spoke classes ]
> + """
> +
> + ret = {}
> +
> + # Collect all the categories this hub displays, then collect all the
> + # spokes belonging to all those categories.
> + candidate_spokes = collect_spokes(self.paths["spokes"])
> + spokes = [spoke for spoke in candidate_spokes \
> + if spoke.should_run("firstboot", self.data)]
> +
> + for spoke in spokes:
> + ret.setdefault(spoke.category, [])
> + ret[spoke.category].append(spoke)
> +
> + return ret
> +
> + @property
> + def continueButton(self):
> + return self.builder.get_object("continueButton")
> +
> + @property
> + def quitButton(self):
> + return self.builder.get_object("quitButton")
> diff --git a/initial_setup/product.py b/initial_setup/product.py
> new file mode 100644
> index 0000000..9a18c59
> --- /dev/null
> +++ b/initial_setup/product.py
> @@ -0,0 +1,34 @@
> +"""Module providing information about the installed product."""
> +
> +RELEASE_STRING_FILE = "/etc/os-release"
> +
> +def product_title():
> + """
> + Get product title.
> +
> + :return: product title
> + :rtype: str
> +
> + """
> +
> + try:
> + with open(RELEASE_STRING_FILE, "r") as fobj:
> + for line in fobj:
> + (key, _eq, value) = line.strip().partition("=")
> + if not key or not _eq or not value:
> + continue
> + if key == "PRETTY_NAME":
> + return value.strip('"')
> + except IOError:
> + return ""
> +
> +def is_final():
> + """
> + Whether it is a final release of the product or not.
> +
> + :rtype: bool
> +
> + """
> +
> + # doesn't really matter for the Initial Setup
> + return True
> diff --git a/initial_setup/tui/hubs/__init__.py b/initial_setup/tui/hubs/__init__.py
> index 5d166d6..39d8b13 100644
> --- a/initial_setup/tui/hubs/__init__.py
> +++ b/initial_setup/tui/hubs/__init__.py
> @@ -1 +1 @@
> -from .initial_setup import InitialSetupMainHub
> +from .initial_setup_hub import InitialSetupMainHub
> diff --git a/initial_setup/tui/hubs/initial_setup.py b/initial_setup/tui/hubs/initial_setup.py
> deleted file mode 100644
> index a8521ad..0000000
> --- a/initial_setup/tui/hubs/initial_setup.py
> +++ /dev/null
> @@ -1,55 +0,0 @@
> -from pyanaconda.ui.tui.hubs import TUIHub
> -from pyanaconda.ui.tui.spokes import TUISpoke
> -from pyanaconda.ui.common import collect
> -import os
> -
> -__all__ = ["InitialSetupMainHub"]
> -
> -# localization
> -_ = lambda t: t
> -N_ = lambda t: t
> -
> -def collect_spokes(mask_paths):
> - """Return a list of all spoke subclasses that should appear for a given
> - category. Look for them in files imported as module_path % basename(f)
> -
> - :param mask_paths: list of mask, path tuples to search for classes
> - :type mask_paths: list of (mask, path)
> -
> - :return: list of Spoke classes belonging to category
> - :rtype: list of Spoke classes
> -
> - """
> - spokes = []
> - for mask, path in mask_paths:
> - spokes.extend(collect(mask, path,
> - lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
> -
> - print spokes
> - return spokes
> -
> -
> -class InitialSetupMainHub(TUIHub):
> - categories = ["password", "localization"]
> - title = _("Initial setup of Fedora")
> -
> - def _collectCategoriesAndSpokes(self):
> - """collects categories and spokes to be displayed on this Hub
> -
> - :return: dictionary mapping category class to list of spoke classes
> - :rtype: dictionary[category class] -> [ list of spoke classes ]
> - """
> -
> - ret = {}
> -
> - # Collect all the categories this hub displays, then collect all the
> - # spokes belonging to all those categories.
> - candidate_spokes = collect_spokes(self.paths["spokes"])
> - spokes = [spoke for spoke in candidate_spokes \
> - if spoke.should_run("firstboot", self.data)]
> -
> - for spoke in spokes:
> - ret.setdefault(spoke.category, [])
> - ret[spoke.category].append(spoke)
> -
> - return ret
> diff --git a/initial_setup/tui/hubs/initial_setup_hub.py b/initial_setup/tui/hubs/initial_setup_hub.py
> new file mode 100644
> index 0000000..6316179
> --- /dev/null
> +++ b/initial_setup/tui/hubs/initial_setup_hub.py
> @@ -0,0 +1,61 @@
> +from pyanaconda.ui.tui.hubs import TUIHub
> +from pyanaconda.ui.tui.spokes import TUISpoke
> +from pyanaconda.ui.common import collect
> +from initial_setup import product
> +import os
> +
> +__all__ = ["InitialSetupMainHub"]
> +
> +# localization
> +_ = lambda t: t
> +N_ = lambda t: t
> +
> +def collect_spokes(mask_paths):
> + """Return a list of all spoke subclasses that should appear for a given
> + category. Look for them in files imported as module_path % basename(f)
> +
> + :param mask_paths: list of mask, path tuples to search for classes
> + :type mask_paths: list of (mask, path)
> +
> + :return: list of Spoke classes belonging to category
> + :rtype: list of Spoke classes
> +
> + """
> + spokes = []
> + for mask, path in mask_paths:
> + spokes.extend(collect(mask, path,
> + lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
> +
> + print spokes
> + return spokes
> +
> +
> +class InitialSetupMainHub(TUIHub):
> + categories = ["password", "localization"]
> +
> + prod_title = product.product_title()
> + if prod_title:
> + title = _("Initial setup of %(product)s") % {"product": prod_title}
> + else:
> + title = _("Initial setup")
> +
> + def _collectCategoriesAndSpokes(self):
> + """collects categories and spokes to be displayed on this Hub
> +
> + :return: dictionary mapping category class to list of spoke classes
> + :rtype: dictionary[category class] -> [ list of spoke classes ]
> + """
> +
> + ret = {}
> +
> + # Collect all the categories this hub displays, then collect all the
> + # spokes belonging to all those categories.
> + candidate_spokes = collect_spokes(self.paths["spokes"])
> + spokes = [spoke for spoke in candidate_spokes \
> + if spoke.should_run("firstboot", self.data)]
> +
> + for spoke in spokes:
> + ret.setdefault(spoke.category, [])
> + ret[spoke.category].append(spoke)
> +
> + return ret
> diff --git a/initial_setup/tui/tui.py b/initial_setup/tui/tui.py
> index 14b5af2..05cbd2c 100644
> --- a/initial_setup/tui/tui.py
> +++ b/initial_setup/tui/tui.py
> @@ -1,5 +1,5 @@
> from pyanaconda.ui.tui import TextUserInterface
> -#from .product import productName, productVersion
> +from initial_setup.product import product_title, is_final
> from .hubs import InitialSetupMainHub
> from pyanaconda.ui.tui.spokes import StandaloneSpoke
> import pyanaconda.ui.tui.spokes
> @@ -12,25 +12,22 @@ from di import inject, usesclassinject
> _ = lambda t: t
> N_ = lambda t: t
>
> -productTitle = lambda: "Initial Setup of Fedora"
> -isFinal = lambda: False
> -
> QUIT_MESSAGE = N_("Are you sure you want to quit the configuration process?\n"
> "You might end up with unusable system if you do.")
>
> - at inject(productTitle = productTitle, isFinal = isFinal)
> + at inject(product_title = product_title, is_final = is_final)
> class InitialSetupTextUserInterface(TextUserInterface):
> """This is the main text based firstboot interface. It inherits from
> anaconda to make the look & feel as similar as possible.
> """
>
> ENVIRONMENT = "firstboot"
> -
> +
> @usesclassinject
> def __init__(self, storage, payload, instclass):
> TextUserInterface.__init__(self, storage, payload, instclass,
> - productTitle, isFinal, quitMessage = QUIT_MESSAGE)
> -
> + product_title, is_final, quitMessage = QUIT_MESSAGE)
> +
> def _list_hubs(self):
> return [InitialSetupMainHub]
>
Looks fine, thanks!
More information about the anaconda-patches
mailing list