0
$\begingroup$

Rosanswers logo

I have a python package and want to copy a folder "models", that have subfolders, to installation path. In setup.py file I have tried to do that including the following lines of code:

    data_files=[
    ('share/ament_index/resource_index/packages',
        ['resource/' + package_name]),
    ('share/' + package_name, ['package.xml']),
    (os.path.join('share', package_name, 'models'), glob('models/**', recursive=True)),]

But when I build the package I get this error: "error: can't copy 'models/': doesn't exist or not a regular file".

Please, could someone tell me how I can do it?

Thank you very much in advance for your help.


Originally posted by joseecm on ROS Answers with karma: 130 on 2022-03-09

Post score: 2


Original comments

Comment by scottie on 2023-05-18:
Are you trying to package this code with a wheel or debian? If you're using debian, you can use the install(DIRECTORY) command in CMakeLists.txt to copy folders.

Comment by joseecm on 2023-05-27:
Hello @scotie, thanks for your answer. My package is a python package, so It doesn't have a CMakeLists.txt.

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

I have finally managed to solve the problem by creating a function that reads the directory tree and includes the information in DATA_FILES. Here is an example in case someone finds it useful. In the code the "models/" and "worlds/" folders contain subfolders. If anyone knows a simpler way to do this I would be very grateful if you would share the information.

import os
from glob import glob
from setuptools import setup

package_name = 'myrobot_gazebo'

data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ]


def package_files(data_files, directory_list):

    paths_dict = {}

    for directory in directory_list:
        
        for (path, directories, filenames) in os.walk(directory):

            for filename in filenames:

                file_path = os.path.join(path, filename)
                install_path = os.path.join('share', package_name, path)
                
                if install_path in paths_dict.keys():
                    paths_dict[install_path].append(file_path)
                    
                else:
                    paths_dict[install_path] = [file_path]
                
    for key in paths_dict.keys():
        data_files.append((key, paths_dict[key]))

    return data_files


setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=package_files(data_files, ['models/', 'launch/', 'worlds/']),
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='ros',
    maintainer_email='[email protected]',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)

Best regards.


Originally posted by joseecm with karma: 130 on 2022-03-11

This answer was ACCEPTED on the original site

Post score: 4

$\endgroup$
0
$\begingroup$

For anyone who stumbles upon this in 2023. You can also use the following list comprehension to generate the tuples:

[(os.path.join('share', package_name, os.path.split(path)[0]), [path]) for path in glob.glob('models/**', recursive=True)]

Then just concatinate it with the data files list.

Best regards.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.