./setup.py publish

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Damit das hochladen nach PyPi einfach ist, hab ich ein wenig code dafür mit in die setup.py gepackt.

Erst hatte ich irgendwo das gesehen:

Code: Alles auswählen

if "publish" in sys.argv:
    import subprocess
    args = [sys.executable or "python", "setup.py", "sdist", "bdist_wheel", "upload"]
    print("\nCall: %r\n" %  " ".join(args))
    subprocess.call(args)

    print("\nDon't forget to tag this version, e.g.:")
    print("\tgit tag v%s" % VERSION_STRING)
    print("\tgit push --tags")
    sys.exit()
Später hab ich mir überlegt, das man ja auch gleich ein wenig testen kann, ob das Hochladen wirklich Sinnvoll ist.
Aktuelle nutzte ich das:

Code: Alles auswählen

if "publish" in sys.argv:
    try:
        # Test if wheel is installed, otherwise the user will only see:
        #   error: invalid command 'bdist_wheel'
        import wheel
    except ImportError as err:
        print("\nError: %s" % err)
        print("\nMaybe https://pypi.python.org/pypi/wheel is not installed or virtualenv not activated?!?")
        print("e.g.:")
        print("    ~/your/env/$ source bin/activate")
        print("    ~/your/env/$ pip install wheel")
        sys.exit(-1)

    if "dev" in __version__:
        print("\nERROR: Version contains 'dev': v%s\n" % __version__)
        sys.exit(-1)

    import subprocess

    def verbose_check_output(*args):
        print("\nCall: %r\n" %  " ".join(args))
        try:
            return subprocess.check_output(args, universal_newlines=True)
        except subprocess.CalledProcessError as err:
            print("\n***ERROR:")
            print(err.output)
            raise

    def verbose_check_call(*args):
        print("\nCall: %r\n" %  " ".join(args))
        subprocess.check_call(args, universal_newlines=True)

    # Check if we are on 'master' branch:
    output = verbose_check_output("git", "branch", "--no-color")
    if "* master" in output:
        print("OK")
    else:
        print("\nNOTE: It seems you are not on 'master':")
        print(output)
        if input("\nPublish anyhow? (Y/N)").lower() not in ("y", "j"):
            print("Bye.")
            sys.exit(-1)

    # publish only if git repro is clean:
    output = verbose_check_output("git", "status", "--porcelain")
    if output == "":
        print("OK")
    else:
        print("\n***ERROR: git repro not clean:")
        print(output)
        sys.exit(-1)

    # tag first (will raise a error of tag already exists)
    verbose_check_call("git", "tag", "v%s" % __version__)

    # build and upload to PyPi:
    verbose_check_call(sys.executable or "python", "setup.py", "sdist", "bdist_wheel", "upload")

    # push
    verbose_check_call("git", "push")
    verbose_check_call("git", "push", "--tags")

    sys.exit(0)
Das ganze könnte man noch weiter ausbauen und muß evtl. an eigene Bedürfnisse angepasst werden...
Aber dazu gibt es ja auch gesonderte Projekte wie z.B.: https://github.com/zestsoftware/zest.releaser

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Dumm nur dass nicht du was auf PyPI hochlädst sondern derjenige der eine MitM Attacke auf dich ausführt ;) Schau dir mal Twine an, um den Upload zu machen.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Recht du hast... Ich update:

Code: Alles auswählen

if "publish" in sys.argv:
    """
    Build and upload to PyPi, if...
        ... __version__ doesn't contains "dev"
        ... we are on git 'master' branch
        ... git repository is 'clean' (no changed files)

    Upload with "twine", git tag the current version and git push --tag

    The cli arguments will be pass to 'twine'. So this is possible:
     * Display 'twine' help page...: ./setup.py publish --help
     * use testpypi................: ./setup.py publish --repository=test
    """
    # Imports here, so it's easier to copy&paste this complete code block ;)
    import subprocess
    import shutil

    try:
        # Test if wheel is installed, otherwise the user will only see:
        #   error: invalid command 'bdist_wheel'
        import wheel
    except ImportError as err:
        print("\nError: %s" % err)
        print("\nMaybe https://pypi.python.org/pypi/wheel is not installed or virtualenv not activated?!?")
        print("e.g.:")
        print("    ~/your/env/$ source bin/activate")
        print("    ~/your/env/$ pip install wheel")
        sys.exit(-1)

    try:
        import twine
    except ImportError as err:
        print("\nError: %s" % err)
        print("\nMaybe https://pypi.python.org/pypi/twine is not installed or virtualenv not activated?!?")
        print("e.g.:")
        print("    ~/your/env/$ source bin/activate")
        print("    ~/your/env/$ pip install twine")
        sys.exit(-1)

    def verbose_check_output(*args):
        """ 'verbose' version of subprocess.check_output() """
        call_info = "Call: %r" % " ".join(args)
        try:
            output = subprocess.check_output(args, universal_newlines=True, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as err:
            print("\n***ERROR:")
            print(err.output)
            raise
        return call_info, output

    def verbose_check_call(*args):
        """ 'verbose' version of subprocess.check_call() """
        print("\tCall: %r\n" % " ".join(args))
        subprocess.check_call(args, universal_newlines=True)

    if "dev" in __version__:
        print("\nERROR: Version contains 'dev': v%s\n" % __version__)
        sys.exit(-1)

    print("\nCheck if we are on 'master' branch:")
    call_info, output = verbose_check_output("git", "branch", "--no-color")
    print("\t%s" % call_info)
    if "* master" in output:
        print("OK")
    else:
        print("\nNOTE: It seems you are not on 'master':")
        print(output)
        if input("\nPublish anyhow? (Y/N)").lower() not in ("y", "j"):
            print("Bye.")
            sys.exit(-1)

    print("\ncheck if if git repro is clean:")
    call_info, output = verbose_check_output("git", "status", "--porcelain")
    print("\t%s" % call_info)
    if output == "":
        print("OK")
    else:
        print("\n *** ERROR: git repro not clean:")
        print(output)
        sys.exit(-1)

    print("\ngit tag version (will raise a error of tag already exists)")
    verbose_check_call("git", "tag", "v%s" % __version__)

    print("\nCleanup old builds:")
    def rmtree(path):
        path = os.path.abspath(path)
        print("\tremove tree:", path)
        shutil.rmtree(path)
    rmtree("./dist")
    rmtree("./build")

    print("\nbuild but don't upload...")
    log_filename="build.log"
    with open(log_filename, "a") as log:
        call_info, output = verbose_check_output(
            sys.executable or "python",
            "setup.py", "sdist", "bdist_wheel", "bdist_egg"
        )
        print("\t%s" % call_info)
        log.write(call_info)
        log.write(output)
    print("Build output is in log file: %r" % log_filename)

    print("\nUpload with twine:")
    twine_args = sys.argv[1:]
    twine_args.remove("publish")
    twine_args.insert(1, "dist/*")
    print("\ttwine upload command args: %r" % " ".join(twine_args))
    from twine.commands.upload import main as twine_upload
    twine_upload(twine_args)

    print("\ngit push to server")
    verbose_check_call("git", "push")
    verbose_check_call("git", "push", "--tags")

    sys.exit(0)
auch hier: https://gist.github.com/jedie/e356a0c17ac1a2fcb716


Aber ich glaub, es ist langsam besser, was fertiges wie https://github.com/zestsoftware/zest.releaser zu nutzten. Der code ist zu viel und zu unübersichtlich und tests fehlen auch ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten