Deployment issues with Hy

Hi, I’ve this minimal application:

main.py

import hy
from logics import double_value
import direct.directbase.DirectStart
from direct.gui.OnscreenText import *
from direct.gui.DirectGui import *
t = OnscreenText(text='', pos=(0, .1))
DirectEntry(
    scale=.05,
    command=lambda text: t.setText(str(double_value(int(text)))),
    focus=1)
base.run()

logics.hy

(defn double_value [n] (* n 2))

If I launch it with python main.py everything works (it doubles the number inserted in the entry field).

Anyway, if I try to create a build of this program (with python setup.py build_apps) using the following files:

setup.py

from setuptools import setup
setup(
    name='try_hy',
    options={
        'build_apps': {
            'gui_apps': {'try_hy': 'main.py'},
            'log_filename': '$USER_APPDATA/try_hy/output.log',
            'log_append': False,
            'include_modules': {'*': ['hy']},
            'include_patterns': ['**/*.hy',],
            'plugins': ['pandagl']}})

requirements.txt

panda3d
hy

When I run the build, it doesn’t work and I get this in the log:

Traceback (most recent call last):
  File "__main__", line 2, in <module>
  File "importlib._bootstrap", line 1027, in _find_and_load
  File "importlib._bootstrap", line 1006, in _find_and_load_unlocked
  File "importlib._bootstrap", line 688, in _load_unlocked
  File "importlib._bootstrap_external", line 879, in exec_module
  File "importlib._bootstrap_external", line 1017, in get_code
  File "hy.importer", line 128, in _hy_source_to_code
  File "hy.compiler", line 2167, in hy_compile
  File "hy.compiler", line 396, in __init__
  File "hy.macros", line 230, in load_macros
  File "importlib", line 126, in import_module
  File "importlib._bootstrap", line 1050, in _gcd_import
  File "importlib._bootstrap", line 1027, in _find_and_load
  File "importlib._bootstrap", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'hy.core.bootstrap'

Where is my error? Thank you very much!

Hmm… I may be mistaken, but it looks to me as though there’s a separate module in Hy that is imported in such a way that it’s not detected by the build system.

If so, then the answer might be to explicitly include that module in the “include_modules” section of your “setup.py” file.

With a bit of searching, I also found this on GitHub, which purports to show how to build a project that uses Hy:

(I can’t, of course, speak to its accuracy.)

1 Like

That’s not the case here.

Hy registers a custom importer so that .hy modules (like hy.core.bootstrap) can be loaded as though they were Python modules. Panda3D doesn’t know to recognise .hy files as modules, or how to compile them to Python bytecode.

Please put in a feature request on GitHub if you would like Panda’s deployment system to have special support for .hy modules.

You could also choose to include the Hy package (contents of the Hy wheel) with the associated .hy files by just copying them into the installation directory, rather than having Panda’s build system process them.

2 Likes

Hi, thank you very much for the answers and for the solution!

Here is another way (pre-compiling the hy files), if anyone needs it.

setup.py

from setuptools import setup
from direct.dist.commands import build_apps
from pathlib import Path
from os import system, remove


class BuildAppsCommand(build_apps):

    def run(self):
        self.__compile_hy_files()
        super().run()
        self.__clean_compiled_hy_files()

    def __compile_hy_files(self):
        hy_files = Path('.').rglob('*.hy')
        for hy_file in hy_files:
            py_file = str(hy_file)[:-2] + 'py'
            system(f'hy2py {hy_file} -o {py_file}')

    def __clean_compiled_hy_files(self):
        hy_files = Path('.').rglob('*.hy')
        for hy_file in hy_files:
            py_file = str(hy_file)[:-2] + 'py'
            remove(py_file)

setup(
    name='try_hy',
    cmdclass={
        'build_apps': BuildAppsCommand},
    options={
        'build_apps': {
            'gui_apps': {'try_hy': 'main.py'},
            'log_filename': '$USER_APPDATA/try_hy/output.log',
            'log_append': False,
            'plugins': ['pandagl']}})
4 Likes

This is a great solution!

1 Like