Browse Source

Add commands sections to config file reading, +example

Thomas Kluyver 9 years ago
parent
commit
af2aa77416

+ 6 - 1
examples/console/installer.cfg

@@ -6,9 +6,14 @@ entry_point=guessnumber:main
 console=true
 
 [Python]
-version=3.5.0rc1
+version=3.5.1
 bitness=64
 format=bundled
 
 [Include]
 packages=guessnumber
+
+# This optional section adds a command which can be run from the Windows
+# command prompt.
+[Command guessnumber]
+entry_point=guessnumber:main

+ 8 - 2
nsist/__init__.py

@@ -76,7 +76,8 @@ class InstallerBuilder(object):
             in the config file
     :param str icon: Path to an icon for the application
     :param list packages: List of strings for importable packages to include
-    :param list commands: List of dicts for commands to define.
+    :param dict commands: Dictionary keyed by command name, containing dicts
+            defining the commands, as in the config file.
     :param list pypi_wheel_reqs: Package specifications to fetch from PyPI as wheels
     :param list extra_files: List of 2-tuples (file, destination) of files to include
     :param list exclude: Paths of files to exclude that would otherwise be included
@@ -100,7 +101,7 @@ class InstallerBuilder(object):
         self.exclude = [os.path.normpath(p) for p in (exclude or [])]
         self.extra_files = extra_files or []
         self.pypi_wheel_reqs = pypi_wheel_reqs or []
-        self.commands = commands or []
+        self.commands = commands or {}
 
         # Python options
         self.py_version = py_version
@@ -452,6 +453,9 @@ if __name__ == '__main__':
                 self.fetch_pylauncher()
         
         self.prepare_shortcuts()
+
+        if self.commands:
+            self.prepare_commands()
         
         # Packages
         self.prepare_packages()
@@ -492,6 +496,7 @@ def main(argv=None):
     try:
         cfg = configreader.read_and_validate(config_file)
         shortcuts = configreader.read_shortcuts_config(cfg)
+        commands = configreader.read_commands_config(cfg)
     except configreader.InvalidConfig as e:
         logger.error('Error parsing configuration file:')
         logger.error(str(e))
@@ -504,6 +509,7 @@ def main(argv=None):
             version = appcfg['version'],
             icon = appcfg.get('icon', DEFAULT_ICON),
             shortcuts = shortcuts,
+            commands=commands,
             packages = cfg.get('Include', 'packages', fallback='').splitlines(),
             pypi_wheel_reqs = cfg.get('Include', 'pypi_wheels', fallback='').splitlines(),
             extra_files = configreader.read_extra_files(cfg),

+ 1 - 1
nsist/_rewrite_shebangs.py

@@ -20,7 +20,7 @@ def rewrite(path):
     if contents[0].strip() != b'#!python':
         return
 
-    contents[0] = b'#!' + b_python_exe + b'\n'
+    contents[0] = b'#!"' + b_python_exe + b'"\n'
 
     with open(path, 'wb') as f:
         f.writelines(contents)

+ 3 - 0
nsist/_system_path.py

@@ -190,3 +190,6 @@ def main():
     elif sys.argv[1] == 'remove':
         remove_from_system_path(sys.argv[2])
         broadcast_environment_settings_change()
+
+if __name__ == '__main__':
+    main()

+ 1 - 2
nsist/commands.py

@@ -20,8 +20,7 @@ if __name__ == '__main__':
 
 def prepare_bin_directory(target, commands, bitness=32):
     exe_src = win_cli_launchers.find_exe('x64' if bitness == 64 else 'x86')
-    for command in commands:
-        name = command['name']
+    for name, command in commands.items():
         shutil.copy(exe_src, str(target / (name+'.exe')))
 
         specified_preamble = command.get('extra_preamble', None)

+ 25 - 1
nsist/configreader.py

@@ -87,6 +87,10 @@ CONFIG_VALIDATORS = {
         ('console', False),
         ('extra_preamble', False),
     ]),
+    'Command': SectionValidator([
+        ('entry_point', True),
+        ('extra_preamble', False),
+    ])
 }
 
 class InvalidConfig(ValueError):
@@ -102,6 +106,8 @@ def read_and_validate(config_file):
             CONFIG_VALIDATORS[section].check(config, section)
         elif section.startswith('Shortcut '):
             CONFIG_VALIDATORS['Shortcut'].check(config, section)
+        elif section.startswith('Command '):
+            CONFIG_VALIDATORS['Command'].check(config, section)
         else:
             valid_section_names = CONFIG_VALIDATORS.keys()
             err_msg = ("{0} is not a valid section header. Must "
@@ -134,7 +140,7 @@ def read_shortcuts_config(cfg):
     There is one shortcut per 'Shortcut <name>' section, and one for the
     Application section.
     
-    Returns a list of dictionaries with the fields from the shortcut sections.
+    Returns a dict of dicts with the fields from the shortcut sections.
     The optional 'icon' and 'console' fields will be filled with their
     default values if not supplied.
     """
@@ -175,3 +181,21 @@ def read_shortcuts_config(cfg):
     _check_shortcut(appcfg['name'], appcfg, 'Application')
 
     return shortcuts
+
+def read_commands_config(cfg):
+    """Read and verify the command definitions from the config file.
+
+    Returns a dict of dicts, keyed by command name, containing the values from
+    the command sections of the config file.
+    """
+    commands = {}
+    for section in cfg.sections():
+        if section.startswith("Command "):
+            name = section[len("Command "):]
+            commands[name] = cc = dict(cfg[section])
+            if ('extra_preamble' in cc) and \
+                    not os.path.isfile(cc['extra_preamble']):
+                raise InvalidConfig('extra_preamble file %r does not exist' %
+                                    cc['extra_preamble'])
+
+    return commands