text: from __future__ import print_function
  from distutils import log
  from setuptools import setup, find_packages, Command
  from setuptools.command.sdist import sdist
  from setuptools.command.build_py import build_py
  from setuptools.command.egg_info import egg_info
  from subprocess import check_call
  import os
  import sys
  import platform
  
  here = os.path.dirname(os.path.abspath(__file__))
  node_root = os.path.join(here, 'js')
  is_repo = os.path.exists(os.path.join(here, '.git'))
  
  npm_path = os.pathsep.join([
      os.path.join(node_root, 'node_modules', '.bin'),
      os.environ.get('PATH', os.defpath),
  ])
  
  log.set_verbosity(log.DEBUG)
  log.info('setup.py entered')
  log.info('$PATH=%s' % os.environ['PATH'])
  
  
  def readme():
      with open('README.rst') as fp:
          return fp.read()
  
  
  def js_prerelease(command, strict=False):
      """decorator for building minified js/css prior to another command"""
      class DecoratedCommand(command):
          def run(self):
              jsdeps = self.distribution.get_command_obj('jsdeps')
              if not is_repo and all(os.path.exists(t) for t in jsdeps.targets):
                  # sdist, nothing to do
                  command.run(self)
                  return
  
              try:
                  self.distribution.run_command('jsdeps')
              except Exception as e:
                  missing = [t for t in jsdeps.targets if not os.path.exists(t)]
                  if strict or missing:
                      log.warn('rebuilding js and css failed')
                      if missing:
                          log.error('missing files: %s' % missing)
                      raise e
                  else:
                      log.warn('rebuilding js and css failed (not a problem)')
                      log.warn(str(e))
              command.run(self)
              update_package_data(self.distribution)
      return DecoratedCommand
  
  
  def update_package_data(distribution):
      """update package_data to catch changes during setup"""
      build_py = distribution.get_command_obj('build_py')
      # distribution.package_data = find_package_data()
      # re-init build_py options which load package_data
      build_py.finalize_options()
  
  
  class NPM(Command):
      description = 'install package.json dependencies using npm'
  
      user_options = []
  
      node_modules = os.path.join(node_root, 'node_modules')
  
      targets = [
          os.path.join(here, 'itkwidgets', 'static', 'extension.js'),
          os.path.join(here, 'itkwidgets', 'static', 'index.js')
      ]
  
      def initialize_options(self):
          pass
  
      def finalize_options(self):
          pass
  
      def get_npm_name(self):
          npmName = 'npm'
          if platform.system() == 'Windows':
              npmName = 'npm.cmd'
  
          return npmName
  
      def has_npm(self):
          npmName = self.get_npm_name()
          try:
              check_call([npmName, '--version'])
              return True
          except BaseException:
              return False
  
      def run(self):
          has_npm = self.has_npm()
          if not has_npm:
              log.error(
                  "`npm` unavailable.  If you're running this command using sudo, make sure `npm` is available to sudo")
  
          env = os.environ.copy()
          env['PATH'] = npm_path
  
          log.info(
              "Installing build dependencies with npm.  This may take a while...")
          npmName = self.get_npm_name()
          check_call([npmName, 'ci'], cwd=node_root,
                     stdout=sys.stdout, stderr=sys.stderr)
          check_call([npmName, 'run', 'build'], cwd=node_root,
                     stdout=sys.stdout, stderr=sys.stderr)
          os.utime(self.node_modules, None)
  
          for t in self.targets:
              if not os.path.exists(t):
                  msg = 'Missing file: %s' % t
                  if not has_npm:
                      msg += '\nnpm is required to build a development version of a widget extension'
                  raise ValueError(msg)
  
          # update package data in case this created new files
          update_package_data(self.distribution)
  
  
  version_ns = {}
  with open(os.path.join(here, 'itkwidgets', '_version.py')) as f:
      exec(f.read(), {}, version_ns)
  
  setup_args = {
      'name': 'itkwidgets',
      'version': version_ns['__version__'],
      'description': 'Interactive Jupyter widgets to visualize images, point sets, and meshes in 2D and 3D',
      'long_description': readme(),
      'long_description_content_type': 'text/x-rst',
      'include_package_data': True,
      'data_files': [
          ('share/jupyter/nbextensions/itkwidgets', [
              'itkwidgets/static/extension.js',
              'itkwidgets/static/index.js',
              'itkwidgets/static/index.js.map'
          ],),
          ('etc/jupyter/nbconfig/notebook.d', ['itkwidgets.json']),
          ('share/jupyter/nbextensions/itkwidgets/itk/Pipelines', [
              'itkwidgets/static/itk/Pipelines/ZstdDecompressWasm.js',
              'itkwidgets/static/itk/Pipelines/ZstdDecompressWasm.wasm',
              'itkwidgets/static/itk/Pipelines/ZstdDecompress.js',
          ]),
          ('share/jupyter/nbextensions/itkwidgets/itk/WebWorkers', [
              'itkwidgets/static/itk/WebWorkers/Pipeline.worker.js'
          ]),
      ],
      'install_requires': [
          'colorcet>=2.0.0',
          'itk-core>=5.2.0',
          'itk-filtering>=5.2.0',
          'itk-meshtopolydata>=0.6.2',
          'ipydatawidgets>=4.0.1',
          'ipywidgets>=7.5.1',
          'ipympl>=0.4.1',
          'matplotlib',
          'numpy',
          'six',
          'zstandard',
      ],
      'packages': find_packages(),
      'zip_safe': False,
      'cmdclass': {
          'build_py': js_prerelease(build_py),
          'egg_info': js_prerelease(egg_info),
          'sdist': js_prerelease(sdist, strict=True),
          'jsdeps': NPM,
      },
  
      'author': 'Matthew McCormick',
      'author_email': 'matt.mccormick@kitware.com',
      'url': 'https://github.com/InsightSoftwareConsortium/itkwidgets',
      'keywords': [
          'ipython',
          'jupyter',
          'jupyterlab-extension',
          'widgets',
          'itk',
          'imaging',
          'visualization',
          'webgl',
      ],
      'classifiers': [
          "License :: OSI Approved :: Apache Software License",
          "Programming Language :: Python",
          'Development Status :: 4 - Beta',
          'Framework :: IPython',
          'Intended Audience :: Developers',
          'Intended Audience :: Science/Research',
          'Topic :: Multimedia :: Graphics',
          'Programming Language :: Python :: 3',
          'Programming Language :: Python :: 3.5',
          'Programming Language :: Python :: 3.6',
          'Programming Language :: Python :: 3.7',
      ],
  }
  
  setup(**setup_args)
  