LSSTApplications  20.0.0
LSSTDataManagementBasePackage
Public Member Functions | List of all members
base.packages.Packages Class Reference

Public Member Functions

def __init__ (self, packages)
 
def fromSystem (cls)
 
def read (cls, filename)
 
def write (self, filename)
 
def __len__ (self)
 
def __str__ (self)
 
def __repr__ (self)
 
def __contains__ (self, pkg)
 
def __iter__ (self)
 
def update (self, other)
 
def extra (self, other)
 
def missing (self, other)
 
def difference (self, other)
 

Detailed Description

A table of packages and their versions.

There are a few different types of packages, and their versions are collected
in different ways:

1. Run-time libraries (e.g., cfitsio, fftw): we get their version from
   interrogating the dynamic library
2. Python modules (e.g., afw, numpy; galsim is also in this group even though
   we only use it through the library, because no version information is
   currently provided through the library): we get their version from the
   ``__version__`` module variable. Note that this means that we're only aware
   of modules that have already been imported.
3. Other packages provide no run-time accessible version information (e.g.,
   astrometry_net): we get their version from interrogating the environment.
   Currently, that means EUPS; if EUPS is replaced or dropped then we'll need
   to consider an alternative means of getting this version information.
4. Local versions of packages (a non-installed EUPS package, selected with
   ``setup -r /path/to/package``): we identify these through the environment
   (EUPS again) and use as a version the path supplemented with the ``git``
   SHA and, if the git repo isn't clean, an MD5 of the diff.

These package versions are collected and stored in a Packages object, which
provides useful comparison and persistence features.

Example usage:

.. code-block:: python

    from lsst.base import Packages
    pkgs = Packages.fromSystem()
    print("Current packages:", pkgs)
    old = Packages.read("/path/to/packages.pickle")
    print("Old packages:", old)
    print("Missing packages compared to before:", pkgs.missing(old))
    print("Extra packages compared to before:", pkgs.extra(old))
    print("Different packages: ", pkgs.difference(old))
    old.update(pkgs)  # Include any new packages in the old
    old.write("/path/to/packages.pickle")

Parameters
----------
packages : `dict`
    A mapping {package: version} where both keys and values are type `str`.

Notes
-----
This is essentially a wrapper around a dict with some conveniences.

Definition at line 209 of file packages.py.

Constructor & Destructor Documentation

◆ __init__()

def base.packages.Packages.__init__ (   self,
  packages 
)

Definition at line 259 of file packages.py.

259  def __init__(self, packages):
260  assert isinstance(packages, Mapping)
261  self._packages = packages
262  self._names = set(packages.keys())
263 

Member Function Documentation

◆ __contains__()

def base.packages.Packages.__contains__ (   self,
  pkg 
)

Definition at line 322 of file packages.py.

322  def __contains__(self, pkg):
323  return pkg in self._packages
324 

◆ __iter__()

def base.packages.Packages.__iter__ (   self)

Definition at line 325 of file packages.py.

325  def __iter__(self):
326  return iter(self._packages)
327 

◆ __len__()

def base.packages.Packages.__len__ (   self)

Definition at line 308 of file packages.py.

308  def __len__(self):
309  return len(self._packages)
310 

◆ __repr__()

def base.packages.Packages.__repr__ (   self)

Definition at line 319 of file packages.py.

319  def __repr__(self):
320  return "%s(%s)" % (self.__class__.__name__, repr(self._packages))
321 

◆ __str__()

def base.packages.Packages.__str__ (   self)

Definition at line 311 of file packages.py.

311  def __str__(self):
312  ss = "%s({\n" % self.__class__.__name__
313  # Sort alphabetically by module name, for convenience in reading
314  ss += ",\n".join("%s: %s" % (repr(prod), repr(self._packages[prod])) for
315  prod in sorted(self._names))
316  ss += ",\n})"
317  return ss
318 

◆ difference()

def base.packages.Packages.difference (   self,
  other 
)
Get packages in symmetric difference of self and another `Packages`
object.

Parameters
----------
other : `Packages`
    Other packages to compare against.

Returns
-------
difference : `dict`
    Packages in symmetric difference.  Keys (type `str`) are package
    names; values (type `str`) are their versions.

Definition at line 375 of file packages.py.

375  def difference(self, other):
376  """Get packages in symmetric difference of self and another `Packages`
377  object.
378 
379  Parameters
380  ----------
381  other : `Packages`
382  Other packages to compare against.
383 
384  Returns
385  -------
386  difference : `dict`
387  Packages in symmetric difference. Keys (type `str`) are package
388  names; values (type `str`) are their versions.
389  """
390  return {pkg: (self._packages[pkg], other._packages[pkg]) for
391  pkg in self._names & other._names if self._packages[pkg] != other._packages[pkg]}

◆ extra()

def base.packages.Packages.extra (   self,
  other 
)
Get packages in self but not in another `Packages` object.

Parameters
----------
other : `Packages`
    Other packages to compare against.

Returns
-------
extra : `dict`
    Extra packages. Keys (type `str`) are package names; values
    (type `str`) are their versions.

Definition at line 343 of file packages.py.

343  def extra(self, other):
344  """Get packages in self but not in another `Packages` object.
345 
346  Parameters
347  ----------
348  other : `Packages`
349  Other packages to compare against.
350 
351  Returns
352  -------
353  extra : `dict`
354  Extra packages. Keys (type `str`) are package names; values
355  (type `str`) are their versions.
356  """
357  return {pkg: self._packages[pkg] for pkg in self._names - other._names}
358 

◆ fromSystem()

def base.packages.Packages.fromSystem (   cls)
Construct a `Packages` by examining the system.

Determine packages by examining python's `sys.modules`, runtime
libraries and EUPS.

Returns
-------
packages : `Packages`

Definition at line 265 of file packages.py.

265  def fromSystem(cls):
266  """Construct a `Packages` by examining the system.
267 
268  Determine packages by examining python's `sys.modules`, runtime
269  libraries and EUPS.
270 
271  Returns
272  -------
273  packages : `Packages`
274  """
275  packages = {}
276  packages.update(getPythonPackages())
277  packages.update(getRuntimeVersions())
278  packages.update(getEnvironmentPackages()) # Should be last, to override products with LOCAL versions
279  return cls(packages)
280 

◆ missing()

def base.packages.Packages.missing (   self,
  other 
)
Get packages in another `Packages` object but missing from self.

Parameters
----------
other : `Packages`
    Other packages to compare against.

Returns
-------
missing : `dict`
    Missing packages. Keys (type `str`) are package names; values
    (type `str`) are their versions.

Definition at line 359 of file packages.py.

359  def missing(self, other):
360  """Get packages in another `Packages` object but missing from self.
361 
362  Parameters
363  ----------
364  other : `Packages`
365  Other packages to compare against.
366 
367  Returns
368  -------
369  missing : `dict`
370  Missing packages. Keys (type `str`) are package names; values
371  (type `str`) are their versions.
372  """
373  return {pkg: other._packages[pkg] for pkg in other._names - self._names}
374 

◆ read()

def base.packages.Packages.read (   cls,
  filename 
)
Read packages from filename.

Parameters
----------
filename : `str`
    Filename from which to read.

Returns
-------
packages : `Packages`

Definition at line 282 of file packages.py.

282  def read(cls, filename):
283  """Read packages from filename.
284 
285  Parameters
286  ----------
287  filename : `str`
288  Filename from which to read.
289 
290  Returns
291  -------
292  packages : `Packages`
293  """
294  with open(filename, "rb") as ff:
295  return pickle.load(ff)
296 

◆ update()

def base.packages.Packages.update (   self,
  other 
)
Update packages with contents of another set of packages.

Parameters
----------
other : `Packages`
    Other packages to merge with self.

Notes
-----
No check is made to see if we're clobbering anything.

Definition at line 328 of file packages.py.

328  def update(self, other):
329  """Update packages with contents of another set of packages.
330 
331  Parameters
332  ----------
333  other : `Packages`
334  Other packages to merge with self.
335 
336  Notes
337  -----
338  No check is made to see if we're clobbering anything.
339  """
340  self._packages.update(other._packages)
341  self._names.update(other._names)
342 

◆ write()

def base.packages.Packages.write (   self,
  filename 
)
Write to file.

Parameters
----------
filename : `str`
    Filename to which to write.

Definition at line 297 of file packages.py.

297  def write(self, filename):
298  """Write to file.
299 
300  Parameters
301  ----------
302  filename : `str`
303  Filename to which to write.
304  """
305  with open(filename, "wb") as ff:
306  pickle.dump(self, ff)
307 

The documentation for this class was generated from the following file:
base.packages.getPythonPackages
def getPythonPackages()
Definition: packages.py:87
lsst::base::getRuntimeVersions
std::map< std::string, std::string > getRuntimeVersions()
Return version strings for dependencies.
Definition: versions.cc:54
lsst::afw::geom.transform.transformContinued.cls
cls
Definition: transformContinued.py:33
lsst.pipe.tasks.mergeDetections.write
def write(self, patchRef, catalog)
Write the output.
Definition: mergeDetections.py:388
base.packages.getEnvironmentPackages
def getEnvironmentPackages()
Definition: packages.py:145
set
daf::base::PropertySet * set
Definition: fits.cc:912
astshim.fitsChanContinued.iter
def iter(self)
Definition: fitsChanContinued.py:88