The IPM (IDL Package Manager) class allows you to create, upload, install, update, and uninstall IDL packages that are a collection of files and folders compressed into a ZIP file. The package can contain any types of files, including IDL pro code, IDL save files, Python code, DLMs, or data files. It also contains idlpackage.json and manifest.json files that describes the package.

Packages are installed to the directory defined by the new IDL_PACKAGE_PATH preference, and the IDL path is automatically updated to include the new files.

Actions


IPM.Create

IPM.Install

IPM.List

IPM.Publish

IPM.Query

IPM.Uninstall

IPM.Update

The Package File


A valid IDL package must contain an idlpackage.json file at the top level. Do not rename the .json file. The structure of the file must be valid JSON and should have a structure similar to the following:

{
  "name": "ExtractAttributes",
  "version": "1.0.0",
  "author": "David Stern",
  "url": "http://myrepository.com:8000/",
  "dependencies": [
    {
      "name": "DumpVectorTable",
      "version": ">=1.0.0"
    },
    {
      "name": "ReadShapefile",
      "version": "<2.0"
    },
    {
      "name": "WriteShape_Windows",
      "version": "1.0"
    },
    {
      "name": "WriteShape_Linux",
      "version": "1.0"
    }
  ]
}

Notes:

  • The only field that is required is the "Name" field; all others are optional.

  • All keys are case insensitive.

  • If the package is hosted on GitHub, the "Version" listed in the idlpackage.json should match the version tag in the GitHub repository. Also, when hosting the package on GitHub, you need to create a GitHub "release," which is described in the GitHub Help at https://docs.github.com/en/github/administering-a-repository/managing-releases-in-a-repository.

  • If more than one dependency is needed, they need to be in a JSON list or array; a single dependency can be in a single JSON object. It is recommended that you use semantic versioning when you specify a version. The URL value in a dependency must be a fully-qualified location.

  • The IPM.Create method will automatically create the idlpackage.json file.

  • If your dependency name ends with a special operating system (OS) name or architecture name, then that dependency will only be installed if you are on a platform that matches. In the idlpackage.json above, see the WriteShape_Windows and WriteShape_Linux package names. If you are on Windows then only the WriteShape_Windows package will be installed, while if you are on Linux then only the WriteShape_Linux package will be installed. These package suffixes are case insensitive and can be one of the following:

_Windows

The Manifest File


If you are going to upload a package to an IDL or ENVI repository portal, you will also need to include a manifest.json file that describes the package. The file should have a structure similar to the following:

{
  "type": "IPM",
  "name": "ExtractAttributes",
  "version": "1.0.0",
  "author": "David Stern",
  "uid": "40f14c38732fd7786683681199e3a3c1",
  "description": "Extracts the attributes table of a shapefile.",
  "tags": ["Vector"]
}

Tip: The IPM.Create method will automatically create the manifest.json file.

Example: Create and Upload to an IDL or ENVI Repository Portal


ENVI packages can be installed from an ENVI repository. These packages typically contain ENVI workflows and tasks, but can also contain other IDL code, Python code, or DLMs. On an ENVI repository server, these packages are not directly accessible via a URL, but instead are downloaded or uploaded using a server-side API.

In this example, we are creating a new package that depends upon two existing packages: DumpVectorTable and ReadShapefile. To create the new package:

url = 'http://myrepository.com:8000/'
packagename = 'ExtractAttributes'
dir = getenv('HOME') + '/' + packagename
 
IPM.Create, dir, $
  name = packagename, $
  description = "Extracts the attributes table of a shapefile.", $
  tags = ["Vector"], $
  version = '1.0.0', $
  author = "David Stern", $
  dependencies = [{ $
    name: "DumpVectorTable", $
    version: ">=1.0.0"}, $
    { $
    name: "ReadShapefile", $
    version: "<2.0"} $
    ], $
  url = url

Note that we can specify different URLs for our dependencies. In this case, DumpVectorTable lives on our same server while ReadShapefile resides on a different repository server.

Now that we have created our package folder along with the idlpackage.json and manifest.json files, we can add any required files or subfolders to our package directory.

We can now publish our newly-created package to the server:

IPM.Publish, dir, destination = 'http://myrepository.com:8000/'

To test your package, you can now install it:

IPM.Install, 'http://myrepository.com:8000/', name='ExtractAttributes', version='1.0.0'

IDL prints:

Package: ExtractAttributes, Version: 1.0.0 installed
Package: DumpVectorTable, Version: 1.2.0 installed
Package: ReadShapefile, Version: 1.9.0 installed

Here you can see that three packages were installed on our local system. These packages can be found in your .idl/idl/packages folder. We also see that for DumpVectorTable, we requested a version of at least 1.0.0, and we received version 1.2.0, which is presumably the latest version. For ReadShapefile, we asked for a version less than 2.0, and we received version 1.9.0.

Semantic Versioning


For dependencies and when installing packages, semantic versioning should be used.

Basic Ranges

A basic range has the form >1.2.3. This tells IDL to use the latest version that is after version 1.2.3.

Note: No spaces are allowed between the operator and the version number. Also, no spaces are allowed in the version string itself.

IPM supports the following operators:

= : equal (this is the default when no operator is supplied)

> : greater than

< : less than

>= : greater than or equal to

<= : less than or equal to

Combined Ranges

A space between two basic ranges means both ranges must be satisfied. To use range 1 OR range 2, use " || " between two ranges.

">=1.2 <1.6" means any version greater than or equal to 1.2 but also less than 1.6.

">=1.5 || 1.3" means any version greater than or equal to 1.5, but also allow version 1.3

Major Ranges

The caret (^) comparison operator is for major level changes, i.e., the major version must be the same. This is useful when comparisons of versions as a major change is breaking.

^1.2.3 means any version greater than or equal to 1.2.3, but less than 2.0.0 (>=1.2.3 <2.0.0)

Minor Ranges

The tilde (~) comparison operator is for patch level ranges, i.e., both the major and minor versions must be the same.

~1.2.3 means any version greater than or equal to 1.2.3, but less than 1.3.0 (>=1.2.3 <1.3.0)

IPM::Create


The IPM::Create static method allows you to create or update an IDL package and optionally create a .zip file.

Note: You must supply a NAME to be able to create a valid IDL package. You can specify it with the NAME keyword, or by supplying a valid idlpackage.json file within the folder being zipped.

Examples


The following creates a new package called MathLib:

IPM.Create, 'C:\MyIDL\MyMathLib', NAME='MathLib', VERSION='1.0'

The following creates a new package from an existing folder and adds all the files to a ZIP file:

IPM.Create, 'C:\MyIDL\MyStatsLib', NAME='MyStatsLib', VERSION='1.2', ZIP_FILE=zipFile

Syntax


IPM.Create, PackageFolder, AUTHOR=string, DATE=string, DEPENDENCIES=value, DESCRIPTION=string, NAME=string, PACKAGE_INFO=hash, TAGS=array, URL=string, UID=string, VERSION=string, ZIP_FILE=variable

Arguments


PackageFolder

Set this argument to a scalar string giving the full path to a local folder. If the folder does not exist, it will be created. Two files will be created in the folder: idlpackage.json and manifest.json. If these files already exist then their contents will be updated with new information given by the keywords.

Keywords


AUTHOR

Set this to the name of the package's author. This value will be stored in the idlpackage.json and manifest.json files; it will overwrite any current author value in the file if one exists.

DATE

Set this to a string denoting the date of creation of the current version of the package. This value will be stored in the idlpackage.json and manifest.json files; it will overwrite any current date value in the file if one exists.

DEPENDENCIES

Set this keyword to an array of structures or a list of hashes that describes any dependencies your package requires. Each element in the list should have the form:

{
  name: "mydependency",
  version: ">1.2.3",
}

The version should be specified using semantic versioning.

Each element can also have an additional "url" field that specifies the exactly location. This is necessary for packages from repositories such as github where each package will be in it's own repository. If a dependency does not have a url, it is assumed to be located on the same repository as its parent.

DESCRIPTION

Set this optional keyword to a string giving a description for the package. This value will be written out to the manifest.json file.

NAME

Set this to the name of the package to create. If an idlpackage.json file exists in the folder where you are creating the package, the NAME specified in the json file will be used.

Note: If an idlpackage.json file does not currently exist, then NAME must be specified.

PACKAGE_INFO

If set to a hash or an ordered hash, all the key/value pairs contained will be added to the idlpackage.json file during package creation.

TAGS

Set this optional keyword to an array of strings containing search tags. This value will be written out to the manifest.json file.

UID

Set this optional keyword to a string giving a UID number. This value will be written out to the manifest.json file. If UID is not specified, then IDL will generate a random 32-digit hexadecimal UID.

URL

Set this optional keyword to the full URL that can be used to find this package. For example, https://github.com/envi-idl/mgunit.zip. This value will be stored in the idlpackage.json file and will overwrite any current value in the file, if one exists.

Tip: If you are publishing your package to a repository server which has search capabilities, you will probably not need to specify the URL for your package or any of the dependencies. However, if you are publishing your package to some place like Github, you will most likely need to specify a full URL.

VERSION

Set this to a string denoting the current version of the package. This value will be stored in the idlpackage.jsonand manifest.json files; it will overwrite any current date value in the file if one exists.

ZIP_FILE

Set this keyword to one of the following:

  • If this keyword is not supplied then no ZIP file is created.

  • If this keyword is set to a named variable then a new ZIP file will be created in your system's temporary directory containing all of the package contents. Upon return the ZIP_FILE variable will be set to the full path to this file.

  • If this keyword is set to a string containing a full path name, then a new ZIP file will be created containing all of the package contents.

Tip: Normally, you should not need to use the ZIP_FILE keyword. The IPM.Publish method will automatically ZIP up the contents of a package folder. You only need to use the ZIP_FILE keyword if you want to distribute your package manually.

IPM::Install


The IPM::Install static method allows you to download and install an IDL package. The packages will be unzipped into a folder underneath the !PACKAGE_PATH directory. The new directory name will be taken from the name of the package being installed. By default, any package dependencies will also be downloaded and installed. The IDL path will be updated to include the new installed files.

Example


The following will download the ZIP file for a package and install all of the files, along with any dependent packages. The IDL path will then be updated.

IDL> IPM.Install, 'https://github.com/chris-torrence/idl-adventure'
Package: idl-adventure, Version: 0.9.1 installed
IDL> IPM.List
Number of installed packages: 1
Name: idl-adventure, Version: 0.9.1

Syntax


IPM.Install, Package, FILE=variable, /GET_ONLY, /KEEP_ZIP, NAME=string, PACKAGE_FOLDER=string, /SKIP_DEPENDENCIES, TYPE=string, VERSION=string

Arguments


Package

Set this argument to a scalar string giving the location and name of an IDL package. This can be a complete URL to a location on the local file system, a URL to a location on the web, or sufficient package information to find the package on a repository such at GitHub.

Keywords


FILE

If this is set to an IDL variable, it will return an array that contains the full paths to the downloaded ZIP files, including any dependencies.

GET_ONLY

Set this keyword to download the package ZIP file but not actually do the installation. The FILE keyword can be used to retrieve the location of the downloaded file.

KEEP_ZIP

Set this keyword to keep the ZIP file after installing the package. By default, any downloaded ZIP file will be deleted after it is unpacked and installed.

NAME

Set this keyword to the package name to install. If Package is a full URL that points to a particular package then NAME will be ignored. However, if Package is a repository server with multiple packages, then NAME should be set to the package to install.

PACKAGE_FOLDER

By default, IPM installs new packages in the !PACKAGE_PATH directory. If PACKAGE_FOLDER is set to the full path of an existing folder, the package will be placed in this folder instead.

Note: If PACKAGE_FOLDER is specified, IDL's path is not automatically updated to include the new directories, this must be done manually.

SKIP_DEPENDENCIES

Set this keyword to ignore, and to not download, any dependencies listed in the given package. The default is to download and install all dependencies.

TYPE

Set this keyword to the type of package being installed. If not set, IPM will attempt to determine the type by examining the contents of the package URL. The choices are:

  • localfile
  • remotefile
  • github
  • artifactory
  • idlenvirepository

VERSION

Set this keyword to the version to obtain. See Semantic Versioning for details on the versioning used by the IDL Package Manager.

IPM::List


The IPM::List static method allows you to get a basic list of the packages currently installed. If NAME is not supplied, LIST will list all the currently installed packages. If NAME is supplied, LIST will list only the information for the specified package.

Example


IPM.List

IDL prints:

Number of installed packages: 2
Name: MyMathLib, Version: 3.14
Name: MyStatsLib, Version: 5.10

Syntax


IPM.List, Name, OUTPUT=variable

Arguments


Name

Set this argument to a scalar string giving the name of the installed package.

Keywords


OUTPUT

Set this keyword to an IDL variable that will contain a string array containing all of the output. If OUTPUT is set then messages will not be printed to the console.

IPM::Publish


The IPM::Publish static method allows you to upload a package to a remote server.

Examples


The following will upload a package to an ENVI repository:

IPM.Publish, 'c:\Users\chris\MyPackage', 'https://myrepository.com:8000/'

Syntax


IPM.Publish, Package, Server, TYPE=string

Arguments


Package

Set this argument to a scalar string giving the full path to either a folder containing the package files, or to a ZIP file. If Package is a ZIP file then it will be uploaded unchanged. If Package is a folder, then all of the files and subfolders within Package will be added to a temporary ZIP file, which is then uploaded. Files and folders that begin with a dot "." will be skipped.

Server

Set this argument to an IDL string containing the destination. Typically this would be the URL of the repository server.

Keywords


TYPE

Set this optional keyword to the type of package being uploaded. If not set, IPM will attempt to determine the type by examining the contents of the package and the server URL. The choices are:

  • localfile
  • remotefile
  • github
  • artifactory
  • idlenvirepository

IPM::Query


The IPM::Query static method allows you to see all the details of a given package.

Example


IPM.Query, 'MyMathLib'

IDL prints:

{
  "Name": "MyMathLib",
  "Version": "3.14",
  "Author": "Boris",
  "Dependencies": [
    {
      "Name": "IDL",
      "Version": "^8.7"
    }
  ]
}

Syntax


IPM.QUERY, Package, INFO=variable, PATH=variable

Arguments


Package

Set this argument to a scalar string giving the name of the installed package.

Keywords


INFO

If set to an IDL variable, this keyword will return an ordered hash containing all the information known about the package. If the Package is not installed then INFO will be set to an empty ordered hash.

Tip: If INFO is supplied then no information is printed to the IDL console.

PATH

If set to an IDL variable, this keyword will contain a string giving the full path to the package on your system. If the Package is not installed then PATH will be set to an empty string.

IPM::Uninstall


The IPM::Uninstall static method allows you to remove packages. Removing a package deletes the folder in which the package resides and updates the IDL path to no longer look in that folder.

Example


The following will delete the folders containing the two packages and updates the IDL path.

IPM.Uninstall, ['MyMathLib', 'MyStatsLib']

Syntax


IPM.Uninstall, Name

Arguments


Name

Set this to a String or String array denoting the name(s) of the packages you wish to remove.

Keywords


None

IPM::Update


The IPM::Update static method allows you to update the contents of a given package. If a suitable update is found, the current package will be removed and the new package will then be installed. When UPDATE is called, the dependency tree is searched. If a conflict is found, a message will be printed and no update will occur. In this case, you must manually update each dependent library as needed. If version information cannot be found for a given package, a message will be printed and no update will occur.

Examples


The following will attempt to update MyMathLib from the current version to version 3.2

IPM.Update, 'MyMathLib', VERSION='3.2'

IDL prints:

Package "MyMathLib" was removed
Package: MyMathLib, Version: 3.2 installed

 

The following will attempt to update MyStatsLib to the latest version. But in this case a dependency conflict occurs.

IPM.Update, 'MyStatsLib'

IDL prints:

Cannot update. Conflicts exist with dependencies:
Conflict in package "StatsHelper", Version: 1.2 is currently installed but "MyStatsLib" requires version: ^1.4.1

It is now up to you to decide whether or not it is safe to update StatsHelper to the needed version.

Syntax


IPM.Update, Name, VERSION=string

Arguments


Name

Set this argument to a scalar string giving the name of the installed package.

Keywords


VERSION

Set this keyword to the version to obtain. If no version is specified, IDL will attempt to update to the lastest version found. Some semantic versioning is accepted. See Semantic Versioning for details on the versioning used by the IDL Package Manager.

Version History


8.7.1

Introduced

9.2

Added static methods for Create, Install, List, Query, Uninstall, Update, Publish. Deprecated IPM keywords for the same functions. Removed OUTPUT and QUIET keywords for most routines. Added support for IDL/ENVI Repository Portals and the manifest.json file. For ::Create, added DESCRIPTION, TAGS, and UID keywords. For ::Query, added PATH keyword.

See Also


IDL_PACKAGE_PATH, !PACKAGE_PATH