Commit 752fb424 authored by Tjerk Vreeken's avatar Tjerk Vreeken

Add console scripts for accessible examples and libraries

The examples for RTC-Tools do not come packaged in the pip package, and
neither would the typical installation location be very convenient.
Editable installs with a git repository are of course possible for
developers, but end users need something easier and more accessible.

The same goes for the Modelica libraries. They are now also included as
pip packages, and the location of the Modelica files is therefore not
very accessible.

To solve this, we add two console scripts, that will get placed in PATH
upon installation:
- rtc-tools-download-examples
- rtc-tools-copy-libraries

Note that the Modelica libraries are _copied_ and not symlinked, to
avoid confusion when editing files, and also avoid users inadvertently
deleting the actual Modelica files in the package.

Closes #1032 and #1034
parent b2dc65d6
......@@ -49,4 +49,10 @@ setup(
test_suite = 'nose.collector',
cmdclass = versioneer.get_cmdclass(),
'console_scripts': [
'rtc-tools-download-examples = rtctools.rtctoolsapp:download_examples',
'rtc-tools-copy-libraries = rtctools.rtctoolsapp:copy_libraries',
import logging
import os
import shutil
import sys
from pathlib import Path
import rtctools
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s')
logger = logging.getLogger("rtctools")
def copy_libraries(*args):
if not args:
path = input("Folder to put the Modelica libraries: [.] ") or "."
path = args[0]
if not os.path.exists(path):
sys.exit("Folder '{}' does not exist".format(path))
# pkg_resources can be quite a slow import, so we do it here
import pkg_resources
def _copytree(src, dst, symlinks=False, ignore=None):
if not os.path.exists(dst):
for item in os.listdir(src):
s = os.path.join(src, item)
d = os.path.join(dst, item)
if os.path.isdir(s):
_copytree(s, d, symlinks, ignore)
if not os.path.exists(d):
shutil.copy2(s, d)
elif Path(s).name.lower() == '':
# Pick the largest one, assuming that all plugin packages
# to not provide a meaningful
if os.stat(s).st_size > os.stat(d).st_size:
logger.warning("Overwriting '{}' with '{}' as the latter is larger.".format(d, s))
shutil.copy2(s, d)
logger.warning("Not copying '{}' to '{}' as the latter is larger.".format(s, d))
raise OSError("Could not combine two folders")
dst = Path(path)
library_folders = []
for ep in pkg_resources.iter_entry_points(group='rtctools.libraries.modelica'):
if == "library_folder":
Path(pkg_resources.resource_filename(ep.module_name, ep.attrs[0])))
tlds = {}
for lf in library_folders:
for x in lf.iterdir():
if x.is_dir():
tlds.setdefault(, []).append(x)
for tld, paths in tlds.items():
if Path(tld).exists():
sys.exit("Library with name '{}'' already exists".format(tld))
for p in paths:
_copytree(p, dst /
except OSError:
sys.exit("Failed merging the libraries in package '{}'".format(tld))
sys.exit("Succesfully copied all library folders to '{}'".format(dst.resolve()))
def download_examples(*args):
if not args:
path = input("Folder to download the examples to: [.] ") or "."
path = args[0]
if not os.path.exists(path):
sys.exit("Folder '{}' does not exist".format(path))
path = Path(path)
from urllib.error import HTTPError
from urllib.request import urlretrieve
from zipfile import ZipFile
version = rtctools.__version__
rtc_full_name = 'rtc-tools-{}'.format(version)
local_filename, _ = urlretrieve(
'{}/{}.zip'.format(version, rtc_full_name))
except HTTPError:
sys.exit("Could not found examples for RTC-Tools version {}.".format(version))
with ZipFile(local_filename, 'r') as z:
target = path / 'rtc-tools-examples'
prefix = '{}/examples/'.format(rtc_full_name)
members = [x for x in z.namelist() if x.startswith(prefix)]
shutil.move(prefix, target)
sys.exit("Succesfully downloaded the RTC-Tools examples to '{}'".format(target.resolve()))
except (OSError, FileNotFoundError):
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment