Ifcopenshell: Cant get access to ifcpatch

Created on 11 Feb 2021  Â·  24Comments  Â·  Source: IfcOpenShell/IfcOpenShell

Ive tried to use a multitude of fixes to get access to the ifcpatch command from my anaconda prompt. I installed ifcopenshell from readme into conda. additionally ive installed only the ifcpatch part but this part tells me to use pyinstaller even though the file structure has changed. How can i access the commands directly in prompt?

Sorry if this is a bad question. Im new to packaging in python.

IfcPatch

All 24 comments

ifcopenshell from readme into conda

How did you install precisely? depending on the method you might simply have an outdated version that doesn't have IfcPatch.

Downloading the 0.6 zip from http://ifcopenshell.org/python is a guarantee you have the latest version.

The pyinstaller line is misleading, I consider this a bug and I will fix it.

In addition, IfcPatch was recently changed from a single script into a module (i.e. a directory). As it is now a module, the way we package it has to change. This is also a bug :)

If you're after a quick fix, you can grab it as a single script at this point in history: https://github.com/IfcOpenShell/IfcOpenShell/tree/884e8a5663efc91a63446c8388a50c21d2768459/src/ifcpatch

A heads up that I am extremely busy this week and do not have time to address these bugs immediately, but thank you so much for your report and I will certainly fix them!

Thank you, it worked with an older version of ifcpatch! how can i install the module so that i dont need the location of the python file? @Moult

I guess you just need to copy the folder to your python's
libs/site-packages/ folder

On Thu, Feb 11, 2021, 18:08 produxe notifications@github.com wrote:

Thank you, it worked with an older version of ifcpatch! how can i install
the module so that i dont need the location of the python file? @Moult
https://github.com/Moult

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/IfcOpenShell/IfcOpenShell/issues/1314#issuecomment-777369652,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAHDQVHR2Y2CN6BMRXUIP23S6O3BZANCNFSM4XOMN67A
.

If i do that then i get "cant find '__main__' module in 'ifcpatch' when i run "python ifcpatch " in anaconda prompt. do you know the reason @htlcnn ?

You can import it into other script. It is not written as a module.

import ifcpatch

print(dir(ifcpatch))

Thanks that works :)

I'm reopening this issue since the new IfcPatch in a directory still needs to packaged in a way that people can easily create a command that they can run instead of running it from Python.

@htlcnn would you be interested in fixing this? It would be similar to how bimtester is packaged I guess.

@Moult It's Lunar New Year here. I'll do it after the holiday if it's not urgent.

Happy new year! No rush at all :)

With the very speedy PR by @htlcnn https://github.com/IfcOpenShell/IfcOpenShell/pull/1317 - I _believe_ now you can just do alias ifcpatch='python -m ifcpatch' and then you can run it as a command. (correct me if wrong)

However, I think we should also cater for another scenario where we want to distribute IfcPatch as a prepackged binary. In this case, @htlcnn would you be interested in checking out the new pyinstaller command required? It should be just a minor tweak to the old one. Maybe we should put the pyinstaller command into a makefile to make it easy for devs, and later Github Actions (ping @Krande ).

@Moult what command are you using? I'm not very familiar with pyinstaller. I tried with this spec:

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['ifcpatch\\__init__.py'],
             pathex=['ifcpatch_pyinstaller'],
             binaries=[],
             datas=[],
             hiddenimports=['ifcopenshell.util.selector'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          Tree('.\\ifcpatch', prefix='ifcpatch\\'),  
          [],
          name='ifcpatch',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True )

it built successfully and I was able to run ExtractElements recipe (I added 'ifcopenshell.util.selector' to hiddenimports because ExtractElements used it). But I'm afraid for other recipes, it depends on what libs they import so that we have to add them to hiddenimports.

This _was_ the command that I was using - https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.6.0/src/ifcpatch/__init__.py#L2 but clearly it no longer applies. Are you sure there isn't a simpler solution?

Actually that's the spec file generated with the command pyinstaller ifcpatch/__init__.py --one-file, then I edited it to add hiddenimports and Tree. It seems they can be added as arguments to the first command. Let me try more.

Awesome - when you've worked it out, is it possible to create a Makefile so that we can run make dist and that'll create a standalone. Then, hopefully we can get it auto built :)

@Moult here's the command:

pyinstaller ./__init__.py --onefile --name ifcpatch --clean --add-data ".;ifcpatch" --hidden-import "ifcopenshell.util.selector"

--add-data src/dst separator is ; on Windows, : on Linux. I still had to add --hidden-import just to make it work with ExtractElements. There's -p to add search path, I think we have to use some piping in the terminal, then it depends on what terminal we use (on Windows or Linux)
The arguments are described here: https://pyinstaller.readthedocs.io/en/stable/usage.html#what-to-bundle-where-to-search

@htlcnn a platform arg can be fed into the Makefile so it can be run like make dist PLATFORM=win or make dist PLATFORM=linux and that'll run the appropriate pyinstaller command.

@Moult how about hidden imports?

@htlcnn I think hidden imports makes sense. We don't have that many recipes right now so a quick skim through should be enough to know what we are importing.

@Moult I'm not familiar with Makefile syntax, can I make a make.py file to:

  • Collect external libs in recipes
  • Call pyinstaller to build?

Sure :)

@Moult after googling around, I find it easier to define hidden imports in a list. Here's my code. If it looks ok, I'll create a PR

import os
import subprocess

# add hidden imports in recipes here
HIDDEN_IMPORTS = [
    "ifcopenshell.util.selector",
    "ifcopenshell.util.element",
    "ifcopenshell.util.schema",
    "toposort",
]


def main():
    hiddenimport_args = " ".join('--hiddenimport "{}"'.format(imp) for imp in HIDDEN_IMPORTS)
    cmd = 'pyinstaller ./__init__.py --onefile --clean --add-data ".{}ifcpatch" {}'.format(
        os.pathsep, hiddenimport_args
    )
    subprocess.check_output(cmd, shell=True)


if __name__ == "__main__":
    main()

@htlcnn looks good! Go for it!

Thanks so much @htlcnn ! Closing bug!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

globalcitizen picture globalcitizen  Â·  12Comments

otsoa picture otsoa  Â·  8Comments

AlexanderNitsch picture AlexanderNitsch  Â·  4Comments

olomakovskyi-blackbird picture olomakovskyi-blackbird  Â·  5Comments

theoryshaw picture theoryshaw  Â·  5Comments