Seite 2 von 3

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 08:52
von Fire Spike
bei welcher webseite soll ich eine dokmentation machen? :?:
das testen kommt noch. ich bin gerade am das paket neu packen. :wink:
und hättest du noch eine idee für eine neue funktion?

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 08:54
von Sirius3
Die Dokumentation finden im Modul per doc-Strings statt.

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 08:56
von Fire Spike
kannst du mir das erklären?

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 09:26
von Sirius3

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 10:20
von Fire Spike
ungefähr so?

Code: Alles auswählen

STATUS_FILENAME = "/var/lib/dpkg/status"

def iter_packages():
    """The main function of module."""
    info = []
    with open(STATUS_FILENAME) as infofile:
        for line in infofile:
            if line.startswith(' '):
                # continue content
                info[-1][-1] += '\n' + line[1:].rstrip()
            elif not line.strip():
                # end of block
                if info:
                    yield dict(info)
                info = []
            else:
                key, content = line.split(":", 1)
                info.append([key, content.strip()])
        if info:
            yield dict(info)
            
def package_exists(package_name):
    """This function checks if package exists."""
    return any(info["Package"] == package_name
        for info in iter_packages())

def get_package(package_name):
    """Returns all values of a package in a dictionary."""
    for info in iter_packages():
        if info["Package"] == package_name:
            return info
    raise KeyError("The package does not exist")

def list_package_names():
    """Returns all package names."""
    return [
        info["Package"]
        for info in iter_packages()
    ]

def count_packages():
    """Counts all installed packages."""
    return sum(1 for info in iter_packages())

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 12:23
von Sirius3
Ungefähr so. Jetzt kannst Du Dir noch eine Vorlage aussuchen, wie Du Argumente und Rückgabewerte dokumentierst. Insgesamt sollte noch genauer beschrieben werden, was die Funktionen machen. Der Docstring für das Modul fehlt noch.

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 13:50
von Fire Spike
meinst du so etwas?

Code: Alles auswählen

"""
The module provides information about installed debian packages.
The module can only be executed if the operating system supports debian packages!
"""
STATUS_FILENAME = "/var/lib/dpkg/status"
__author__ = "Ben Fässler <faesslerben@gmail.com>"
__license__ = "MIT"
__all__ = ["iter_packages (not for user)",
           "package_exists",
           "get_package",
           "list_package_names",
           "count_packages"
        ]
__version__ = "0.0.1"

import os

if not os.path.exists(STATUS_FILENAME):
    raise FileNotFoundError("The information file was not found! Without this file, the module can not be executed!")
del os

def iter_packages():
    """The main function of module."""
    info = []
    with open(STATUS_FILENAME) as infofile:
        for line in infofile:
            if line.startswith(' '):
                # continue content
                info[-1][-1] += '\n' + line[1:].rstrip()
            elif not line.strip():
                # end of block
                if info:
                    yield dict(info)
                info = []
            else:
                key, content = line.split(":", 1)
                info.append([key, content.strip()])
        if info:
            yield dict(info)
            
def package_exists(package_name):
    """This function checks if package exists.
Arguments:
    package_name - The name of the package
    """
    return any(info["Package"] == package_name
        for info in iter_packages())

def get_package(package_name):
    """Returns all values of a package in a dictionary.
Arguments:
    package_name - The name of the package
    """
    for info in iter_packages():
        if info["Package"] == package_name:
            return info
    raise KeyError("The package does not exist")

def list_package_names():
    """Returns all package names."""
    return [
        info["Package"]
        for info in iter_packages()
    ]

def count_packages():
    """Counts all installed packages."""
    return sum(1 for info in iter_packages())

Re: Eigenes Modul

Verfasst: Montag 7. Oktober 2019, 16:39
von Sirius3
Auf Modulebene sollte so wenig wie möglich passieren. Das testen, ob die Datei existiert passiert automatisch, wenn man iter_packages aufruft, die Prüfung kann also weg, zumal sie nicht prüft, ob man die Datei auch lesen darf.

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 08:10
von Fire Spike

Code: Alles auswählen

Auf Modulebene sollte so wenig wie möglich passieren
Das weiss ich aber andere module machen das auch so.
Und ich will das schon beim mport ein fehler kommt.

Ich habe noch die Leseberechtigungsabfrage hinugefügt:

Code: Alles auswählen

if not os.path.exists(STATUS_FILENAME):
    raise FileNotFoundError("The information file was not found! Without this file, the module can not be executed!")
else:
    if not os.access(STATUS_FILENAME, os.R_OK):
        raise PermissionError("No reading rights for the information file! Without this file, the module can not be executed!")

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 09:36
von Sirius3
"explicit is better than implicit", heißt, dass Du die Prüfung gerne am Anfang Deines Programms machen kannst, aber nicht beim Import des Moduls. Schreib eine Funktion und ruf die in `main` auf. Die Prüfung will man ja nicht haben, wenn man nur den Hilfstext des Programms ausgegeben lassen will.

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 12:05
von Fire Spike

Code: Alles auswählen

if __name__ == "__main__":
geht nicht soll ich die funktion als erstes in iter_packages() ausführen?

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 12:12
von Sirius3
Warum sollte das auch gehen, dieser if-Block wird ja gerade deshalb benutzt, damit er NICHT beim Importieren eines Moduls ausgeführt wird. Aber Du hast doch ein Programm, in dem dieses Modul verwendet wird, und dort kannst Du doch, wenn Du möchtest, den Check durchführen. In `iter_packages` passiert das automatisch durch `open`, dort ist also nichts weiter zu tun.

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 12:29
von Fire Spike
O.K habe ich gelöscht.
macht diese funktion sinn?
code:

Code: Alles auswählen

def print_documentation():
    for i, a in zip([iter_packages, package_exists, get_package_values, list_package_names, count_packages], __all__):
        print(a)
        print("____________________")
        print(i.__doc__ + "\n")
ausgabe:

Code: Alles auswählen

iter_packages (not for user)
____________________
The main function of module.
    

package_exists
____________________
This function checks if package exists.
Arguments:
    package_name - The name of the package
The function returns True or False.
    

get_package_values
____________________
Returns all values of a package in a dictionary.
Arguments:
    package_name - The name of the package
    

list_package_names
____________________
Returns all names of installed packages.
The function returns the names in a list.
    

count_packages
____________________
Counts all installed packages.
The function returns the number as an integer.

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 13:12
von Sirius3
Das macht ein `help(module)` schon automatisch und viel schöner.

Re: Eigenes Modul

Verfasst: Dienstag 8. Oktober 2019, 14:28
von __blackjack__
Oder ``python3 -m pydoc module.py`` wenn man nicht in einer interaktiven Python-Shell ist.

Re: Eigenes Modul

Verfasst: Donnerstag 10. Oktober 2019, 09:08
von Fire Spike
Ich habe die funktion gelöscht dafür eine neue sinnvolle programmiert. 8)
Erklären muss ich nicht das ist im doc-string. :wink:

Code: Alles auswählen

def package_created_paths(package_name):
    """Returns files and folders created by the package as a path.
Arguments:
    package_name - The name of the package
The function returns the paths in a list.
    """
    paths = []
    filename = package_name + ".md5sums"
    with open(pathlib.PurePath("/var/lib/dpkg/info", filename)) as infofile:
        for info in infofile:
            paths.append(info.split("  ")[1].strip())
        return paths

Re: Eigenes Modul

Verfasst: Donnerstag 10. Oktober 2019, 09:39
von __blackjack__
@Fire Spike: Das stimmt nicht so ganz, denn in der `*.md5sums` stehen nur Dateien drin, die auch im Paket als Datei enthalten sind. Pakete können beim installieren aber auch Dateien erstellen die nicht im Paket als Datei enthalten sind. Beispiel wäre `xpdf` das eine ``/etc/xpdf/includes`` erstellt, die aber nicht in der `*.md5sums`-Datei aufgelistet ist.

Warum `PurePath` statt `Path`? Bei Textdateien sollte man immer eine Kodierung angeben.

Das Splitten wäre mir so zu gefährlich. Es gibt sicher eine Richtlinie das in Dateinamen in Debianpaketen keine Leerzeichen vorkommen dürfen, aber es gibt sicher auch Pakete da draussen die dagegen verstossen. Und es ist ja relativ einfach sich dagegen abzusichern.

Die Einrückung vom Docstring stimmt nicht und ich würde da auch mal schauen ob das so ohne Leerzeilen von Sphinx (mit `napoleon`-Erweiterung) verstanden wird. Wobei die Argumentbeschreibung im Grunde auch überflüssig ist und der letzte Satz auch redundant ist.

Re: Eigenes Modul

Verfasst: Donnerstag 10. Oktober 2019, 11:58
von Fire Spike
giebt es ein anderer ort wo alles drinnen steht? Die paketverwaltung kann ja auch alle deinstallieren.

Code: Alles auswählen

Die Einrückung vom Docstring stimmt nicht
wie würdest den du einrücken?
Was ist sphinx?

Re: Eigenes Modul

Verfasst: Donnerstag 10. Oktober 2019, 13:05
von __blackjack__
@Fire Spike: Die Dateien müssen nicht alle irgendwo stehen weil sowohl beim installieren als auch beim deinstallieren Skripte ausgeführt werden können die beliebige Dinge tun. Unter anderem eben auch Dateien anlegen oder löschen.

Ich würde das so einrücken das die Einrückung des Codes nicht falsch aussieht. Alles unter einem ``def`` sollte mindestens eine Ebene eingerückt sein, denn die erste nicht mehr eingerückte Zeile ist der visuelle Hinweis das die Funktion da zuende ist.

Sphinx ist das Werkzeug mit dem die meisten Python-Projekte (und mittlerweile auch andere) die Dokumentation erstellen. Das kann auch Docstrings aus dem Code in die Dokumentation einbinden, damit man das nicht zweimal schreiben muss. Und für den Stil den Du da für die Argumente gewählt hast, muss man bei Sphinx die `napoleon`-Erweiterung aktivieren. Wobei Dein Stil noch geringfügig abweicht. Ich weiss nicht ob das '-' statt des ':' bei den Argumenten erkannt wird.

Re: Eigenes Modul

Verfasst: Donnerstag 10. Oktober 2019, 15:55
von Fire Spike
@__blackjack__: giebt es eine möglichkeit die installationsskripte zu durchsuchen um die dateien und ordner zu finden.
Ich weiss welche dateien du meinst: *.preinst und *.postinst
ich bin zu dumm für sphinx. ich weiss nicht wo ich die pythondatei hintun soll. :peinlich: :roll:

Code: Alles auswählen

Wobei Dein Stil noch geringfügig abweicht. Ich weiss nicht ob das '-' statt des ':' bei den Argumenten erkannt wird.
wo du recht hast, hast du recht.