diff --git a/.git_archival.txt b/.git_archival.txt
new file mode 100644
index 0000000..95cb3ee
--- /dev/null
+++ b/.git_archival.txt
@@ -0,0 +1 @@
+ref-names: $Format:%D$
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..00a7b00
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+.git_archival.txt export-subst
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2ed460d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2019, sot
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 742390e..6629e7f 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,12 @@
# ska_helpers
+
+This is a collection of utilities for ACA packages.
+It currently includes:
+
+- get_version. A function to get the version from installed package information ot git.
+
+ from ska_helpers import get_version
+ version = get_version('chandra_aca')
+
+ import ska_helpers.version
+ print(ska_helpers.version.parse_version(version))
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..e69de29
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..e67e56a
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = python -msphinx
+SPHINXPROJ = ska_helpers
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..d1e5a4f
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# ska_helpers documentation build configuration file, created by
+# sphinx-quickstart on Fri Dec 13 09:48:53 2019.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import sys
+import os
+sys.path.insert(0, os.path.abspath('..'))
+from ska_helpers import __version__
+
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['sphinx.ext.autodoc',
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.coverage']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'ACA Helpers'
+copyright = '2019, Javier Gonzalez'
+author = 'Javier Gonzalez'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = __version__
+# The full version, including alpha/beta/rc tags.
+release = __version__
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# This is required for the alabaster theme
+# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
+# html_sidebars = {}
+
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'ska_helpers_doc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'ska_helpers.tex', 'aca\\_helpers Documentation',
+ 'Javier Gonzalez', 'manual'),
+]
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'ska_helpers', 'ska_helpers Documentation',
+ [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'ska_helpers', 'ska_helpers Documentation',
+ author, 'ska_helpers', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+
+
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..de328fb
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,65 @@
+.. ska_helpers documentation master file, created by
+ sphinx-quickstart on Fri Dec 13 09:48:53 2019.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+ACA Package Helpers
+===================
+
+.. automodule:: ska_helpers
+ :members:
+
+Get Version
+-----------
+
+.. automodule:: ska_helpers.get_version
+ :members:
+
+
+Default versioning scheme
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+What follows is the scheme as described in `setuptools_scm's documentation `.
+
+In the standard configuration ``setuptools_scm`` takes a look at three things:
+
+1. latest tag (with a version number)
+2. the distance to this tag (e.g. number of revisions since latest tag)
+3. workdir state (e.g. uncommitted changes since latest tag)
+
+and uses roughly the following logic to render the version:
+
+no distance and clean:
+ ``{tag}``
+distance and clean:
+ ``{next_version}.dev{distance}+{scm letter}{revision hash}``
+no distance and not clean:
+ ``{tag}+dYYYMMMDD``
+distance and not clean:
+ ``{next_version}.dev{distance}+{scm letter}{revision hash}.dYYYMMMDD``
+
+The next version is calculated by adding ``1`` to the last numeric component of
+the tag.
+
+For Git projects, the version relies on `git describe `_,
+so you will see an additional ``g`` prepended to the ``{revision hash}``.
+
+
+Due to the default behavior it's necessary to always include a
+patch version (the ``3`` in ``1.2.3``), or else the automatic guessing
+will increment the wrong part of the SemVer (e.g. tag ``2.0`` results in
+``2.1.devX`` instead of ``2.0.1.devX``). So please make sure to tag
+accordingly.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..50d303a
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,19 @@
+# Licensed under a 3-clause BSD style license - see LICENSE.rst
+from setuptools import setup
+
+try:
+ from testr.setup_helper import cmdclass
+except ImportError:
+ cmdclass = {}
+
+setup(name='ska_helpers',
+ description='Utilities for ska packages',
+ author='Javier Gonzalez',
+ author_email='javier.gonzalez@cfa.harvard.edu',
+ url='http://cxc.harvard.edu/mta/ASPECT/tool_doc/ska_helpers.html',
+ packages=['ska_helpers'],
+ tests_require=['pytest'],
+ use_scm_version=True,
+ setup_requires=['setuptools_scm', 'setuptools_scm_git_archive'],
+ cmdclass=cmdclass,
+ )
diff --git a/ska_helpers/__init__.py b/ska_helpers/__init__.py
new file mode 100644
index 0000000..b52b0b9
--- /dev/null
+++ b/ska_helpers/__init__.py
@@ -0,0 +1,11 @@
+"""
+Ska_helpers is a collection of utilities for the Ska3 runtime environment.
+
+ska_helpers.version
+-------------------
+- get_version: get the version from installed package information or git.
+- parse_version: parse the version into a dict of components.
+"""
+from .version import get_version
+
+__version__ = get_version(__package__)
diff --git a/ska_helpers/version.py b/ska_helpers/version.py
new file mode 100644
index 0000000..f418a31
--- /dev/null
+++ b/ska_helpers/version.py
@@ -0,0 +1,101 @@
+"""
+This module provides utilities to handle package versions. The version of a
+package is determined using pkg_resources if it is installed, and
+`setuptools_scm `_ otherwise.
+"""
+
+import re
+import os
+from pathlib import Path
+import importlib
+from pkg_resources import get_distribution, DistributionNotFound
+
+
+def get_version(package, distribution=None):
+ """
+ Get version string for ``package`` with optional ``distribution`` name.
+
+ If the package is not from an installed distribution then get version from
+ git using setuptools_scm.
+
+ :param package: package name, typically __package__
+ :param distribution: name of distribution if different from ``package``
+
+ :return: str
+ Version string
+ """
+ # Get module for package. When called from /__init__.py this is
+ # not circular because that package is already in sys.modules. If the
+ # package does not import then ImportError is raised as normal.
+ module = importlib.import_module(package)
+
+ # From this point guarantee tha a version string is returned.
+ try:
+ try:
+ # Get a distribution, which may or may not correspond to the package
+ # # that gets imported (we check that next). For some packages, e.g.
+ # cheta or pyyaml, the distribution will be different from the
+ # package.
+ dist_info = get_distribution(distribution or package)
+ version = dist_info.version
+
+ # Check if the imported package __init__.py file has the same location
+ # as the distribution that was found. If working in a local git repo
+ # that does not have a .egg-info directory, get_distribution()
+ # will find an installed version. Windows does not necessarily
+ # respect the case so downcase everything.
+ assert module.__file__.lower().startswith(dist_info.location.lower())
+
+ # If the dist_info.location appears to be a git repo, then
+ # get_distribution() has gotten a "local" distribution and the
+ # dist_info.version just corresponds to whatever version was the
+ # last run of "setup.py sdist" or "setup.py bdist_wheel", i.e.
+ # unrelated to current version, so ignore in this case.
+ git_dir = Path(dist_info.location, '.git')
+ if git_dir.exists() and git_dir.is_dir():
+ raise AssertionError
+ print(f'** Using DIST_INFO ({package}, {distribution}):', dist_info.location)
+
+ except (DistributionNotFound, AssertionError):
+ # Get_distribution failed or found a different package from this
+ # file, try getting version from source repo.
+ from setuptools_scm import get_version
+
+ # Define root as N directories up from location of __init__.py based
+ # on package name.
+ roots = ['..'] * len(package.split('.'))
+ if os.path.basename(module.__file__) != '__init__.py':
+ roots = roots[:-1]
+ version = get_version(root=Path(*roots), relative_to=module.__file__)
+ print(f'** Using setuptools_scm ({package}, {distribution})')
+
+ except Exception:
+ # Something went wrong. The ``get_version` function should never block
+ # import but generate a lot of output indicating the problem.
+ import warnings
+ import traceback
+ warnings.warn(traceback.format_exc() + '\n\n')
+ warnings.warn('Failed to find a package version, setting to 0.0.0')
+ version = '0.0.0'
+
+ return version
+
+
+def parse_version(version):
+ """
+ Parse version string and return a dictionary with version information.
+ This only handles the default scheme.
+
+ :param version: str
+ :return: dict
+ """
+ fmt = r'(?P[0-9]+)(.(?P[0-9]+))?(.(?P[0-9]+))?' \
+ r'(.dev(?P[0-9]+))?'\
+ r'(\+(?P\S)g?(?P\S+)\.(d(?P[0-9]+))?)?'
+ m = re.match(fmt, version)
+ if not m:
+ raise RuntimeError(f'version {version} could not be parsed')
+ result = m.groupdict()
+ for k in ['major', 'minor', 'patch', 'distance']:
+ result[k] = eval(f'{result[k]}')
+ return result