Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use module version for version field #127

Open
Alexis-B opened this issue Sep 13, 2017 · 9 comments
Open

Use module version for version field #127

Alexis-B opened this issue Sep 13, 2017 · 9 comments

Comments

@Alexis-B
Copy link

Hi,

I'm trying to configure pynsist (great work by the way) to init the version field using the application module version. In the doc and all exemples, I always see "version=1.0" . Is there a way tu put "version=mymodule.version", of something like that? If not, this would be a great feature.

Alexis

@takluyver
Copy link
Owner

You can't currently do this using a config file, which is the normal way I recommend you use Pynsist. I'll consider it as a possible feature for future versions.

You can do it through the Pynsist Python API, with code something like this:

import mymodule
from nsist import InstallerBuilder

InstallerBuilder('myapp',  mymodule.__version__,
                 ... # Other parameters go here
                ).run()

I consider this API semi-public: it's liable to break more often, and with less helpful error messages, than running Pynsist on a config file.

@Alexis-B
Copy link
Author

Thanks! How would you provide the 'entry_point' parameter using this method? I'm getting various errors with this:

builder = InstallerBuilder( src.__name__, src.__version__, {'Application':{'entry_point':'src.main:main'}}, packages=['PyQt5','sip','matplotlib'], build_dir='packaging' )

The project is not very complex, and the configuration will not change much. So I'm thinking that if it works once, it should be OK...

@takluyver
Copy link
Owner

I think you need to ensure that that shortcut dictionary contains 'icon' and 'console' as well - they're optional in the config file but not in that API.

@Alexis-B
Copy link
Author

Ok, thanks. I finally gave up: I found that I had to provide twice the icon (first in "shortcuts" and then in "icon"), but mainly while I though I gave all informations, the installer create a windows shortcut "Application", instead of the name of the application. Initially my goal was to update the version number from the module, so I'll do it manually (and possibly upgrade if the functionnality is integrated in pynsist).
By the way thanks for your help

@takluyver
Copy link
Owner

No problem. You might want to look at bumpversion as a way to streamline updating the version number in several places.

@cachitas
Copy link
Contributor

cachitas commented Sep 14, 2017

I though I could jump in and leave here, as an example, my use of the builder API with a PyQt5 application. Basically, it looks like this:

import nsist
from pathlib import Path

from src import application

icon = Path('icons', application.ICON).resolve()
requirements = open('requirements.txt').read().strip().split('\n')

builder = nsist.InstallerBuilder(
    appname=application.NAME,
    version=application.VERSION,
    icon=icon,
    shortcuts={
        application.NAME: {
            'entry_point': 'src.application:main',
            'console': False,
            'icon': icon,
        }
    },
    py_version='3.6.0',
    py_bitness=64,
    pypi_wheel_reqs=requirements,
)

builder.run()

I hope this minimal setup can help you. Of course I am open to suggestions to improve it. By no means I claim this is the way to go. I use this in a build.py script where I also prepare the *.ui and resources.qrc files, required by PyQt5.

@Alexis-B
Copy link
Author

Alexis-B commented Oct 6, 2017

Interesting, thanks for this contribution! I think I'll try this at some point and let you know if all is good

@albertogomcas
Copy link

Alternatively, you can use a template for the cfg and fill it at build time.
(This is a very, very rough example which covers just sunny day builds, but a bit of cleanup and combining this with bumpversion can get you going a really long way)

Assumptions are you have a template.cfg with version = $VERSION and inside your package your have a version.py with __version__="major.minor.patch" (the usual)

import os
import glob
import subprocess

PACKAGE = "mypackage"

if __name__ == "__main__":
    exec(open(os.path.join(PACKAGE, "version.py")).read())  # loads __version__ in this scope
    build_config_temp = f"build_{__version__}.cfg"

    with open("build_template.cfg", "rt") as btfile:
        template = btfile.read()
        filled_template = template.replace("$VERSION", __version__)
        with open(build_config_temp, "wt+") as bvfile:
            bvfile.write(filled_template)

    #clean up previous build if exists
    old_builds = glob.glob(f"build/nsis/*{__version__}.exe")
    for ob in old_builds:
        print(f"Deleting {ob}")
        os.remove(ob)

    subprocess.call(f"pynsist {build_config_temp}")
    os.remove(build_config_temp)

@takluyver
Copy link
Owner

If you do use bumpversion (which I'd recommend), you shouldn't need to write a templating layer - just add installer.cfg to the files for bumpversion to update.

The templating approach should work fine too. Amusingly, Pynsist itself uses templating to generate the NSIS file, and NSIS has its own preprocessor system. It's templates all the way down. ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants