class_docstr: Our constructor takes a definition of a Python package similar to that
  passed to `distutils.core.setup()` or `setuptools.setup()` (name, version,
  summary etc) plus callbacks for building, getting a list of sdist
  filenames, and cleaning.
  
  We provide methods that can be used to implement a Python package's
  `setup.py` supporting PEP-517.
  
  We also support basic command line handling for use
  with a legacy (pre-PEP-517) pip, as implemented
  by legacy distutils/setuptools and described in:
  https://pip.pypa.io/en/stable/reference/build-system/setup-py/
  
  Here is a `doctest` example of using pipcl to create a SWIG extension
  module. Requires `swig`.
  
  Create an empty test directory:
  
      >>> import os
      >>> import shutil
      >>> shutil.rmtree('pipcl_test', ignore_errors=1)
      >>> os.mkdir('pipcl_test')
  
  Create a `setup.py` which uses `pipcl` to define an extension module.
  
      >>> import textwrap
      >>> with open('pipcl_test/setup.py', 'w') as f:
      ...     _ = f.write(textwrap.dedent("""
      ...             import sys
      ...             import pipcl
      ...
      ...             def build():
      ...                 so_leaf = pipcl.build_extension(
      ...                         name = 'foo',
      ...                         path_i = 'foo.i',
      ...                         outdir = 'build',
      ...                         )
      ...                 return [
      ...                         ('build/foo.py', 'foo/__init__.py'),
      ...                         (f'build/{so_leaf}', f'foo/'),
      ...                         ('README', '$dist-info/'),
      ...                         ]
      ...
      ...             def sdist():
      ...                 return [
      ...                         'foo.i',
      ...                         'bar.i',
      ...                         'setup.py',
      ...                         'pipcl.py',
      ...                         'wdev.py',
      ...                         'README',
      ...                         ]
      ...
      ...             p = pipcl.Package(
      ...                     name = 'foo',
      ...                     version = '1.2.3',
      ...                     fn_build = build,
      ...                     fn_sdist = sdist,
      ...                     )
      ...
      ...             build_wheel = p.build_wheel
      ...             build_sdist = p.build_sdist
      ...
      ...             # Handle old-style setup.py command-line usage:
      ...             if __name__ == '__main__':
      ...                 p.handle_argv(sys.argv)
      ...             """))
  
  Create the files required by the above `setup.py` - the SWIG `.i` input
  file, the README file, and copies of `pipcl.py` and `wdev.py`.
  
      >>> with open('pipcl_test/foo.i', 'w') as f:
      ...     _ = f.write(textwrap.dedent("""
      ...             %include bar.i
      ...             %{
      ...             #include <stdio.h>
      ...             #include <string.h>
      ...             int bar(const char* text)
      ...             {
      ...                 printf("bar(): text: %s\\n", text);
      ...                 int len = (int) strlen(text);
      ...                 printf("bar(): len=%i\\n", len);
      ...                 fflush(stdout);
      ...                 return len;
      ...             }
      ...             %}
      ...             int bar(const char* text);
      ...             """))
  
      >>> with open('pipcl_test/bar.i', 'w') as f:
      ...     _ = f.write( '\n')
  
      >>> with open('pipcl_test/README', 'w') as f:
      ...     _ = f.write(textwrap.dedent("""
      ...             This is Foo.
      ...             """))
  
      >>> root = os.path.dirname(__file__)
      >>> _ = shutil.copy2(f'{root}/pipcl.py', 'pipcl_test/pipcl.py')
      >>> _ = shutil.copy2(f'{root}/wdev.py', 'pipcl_test/wdev.py')
  
  Use `setup.py`'s command-line interface to build and install the extension
  module into root `pipcl_test/install`.
  
      >>> _ = subprocess.run(
      ...         f'cd pipcl_test && {sys.executable} setup.py --root install install',
      ...         shell=1, check=1)
  
  The actual install directory depends on `sysconfig.get_path('platlib')`:
  
      >>> if windows():
      ...     install_dir = 'pipcl_test/install'
      ... else:
      ...     install_dir = f'pipcl_test/install/{sysconfig.get_path("platlib").lstrip(os.sep)}'
      >>> assert os.path.isfile( f'{install_dir}/foo/__init__.py')
  
  Create a test script which asserts that Python function call `foo.bar(s)`
  returns the length of `s`, and run it with `PYTHONPATH` set to the install
  directory:
  
      >>> with open('pipcl_test/test.py', 'w') as f:
      ...     _ = f.write(textwrap.dedent("""
      ...             import sys
      ...             import foo
      ...             text = 'hello'
      ...             print(f'test.py: calling foo.bar() with text={text!r}')
      ...             sys.stdout.flush()
      ...             l = foo.bar(text)
      ...             print(f'test.py: foo.bar() returned: {l}')
      ...             assert l == len(text)
      ...             """))
      >>> r = subprocess.run(
      ...         f'{sys.executable} pipcl_test/test.py',
      ...         shell=1, check=1, text=1,
      ...         stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
      ...         env=os.environ | dict(PYTHONPATH=install_dir),
      ...         )
      >>> print(r.stdout)
      test.py: calling foo.bar() with text='hello'
      bar(): text: hello
      bar(): len=5
      test.py: foo.bar() returned: 5
      <BLANKLINE>
  
  Check that building sdist and wheel succeeds. For now we don't attempt to
  check that the sdist and wheel actually work.
  
      >>> _ = subprocess.run(
      ...         f'cd pipcl_test && {sys.executable} setup.py sdist',
      ...         shell=1, check=1)
  
      >>> _ = subprocess.run(
      ...         f'cd pipcl_test && {sys.executable} setup.py bdist_wheel',
      ...         shell=1, check=1)
  
  Check that rebuild does nothing.
  
      >>> t0 = os.path.getmtime('pipcl_test/build/foo.py')
      >>> _ = subprocess.run(
      ...         f'cd pipcl_test && {sys.executable} setup.py bdist_wheel',
      ...         shell=1, check=1)
      >>> t = os.path.getmtime('pipcl_test/build/foo.py')
      >>> assert t == t0
  
  Check that touching bar.i forces rebuild.
  
      >>> os.utime('pipcl_test/bar.i')
      >>> _ = subprocess.run(
      ...         f'cd pipcl_test && {sys.executable} setup.py bdist_wheel',
      ...         shell=1, check=1)
      >>> t = os.path.getmtime('pipcl_test/build/foo.py')
      >>> assert t > t0
  
  Check that touching foo.i.cpp does not run swig, but does recompile/link.
  
      >>> t0 = time.time()
      >>> os.utime('pipcl_test/build/foo.i.cpp')
      >>> _ = subprocess.run(
      ...         f'cd pipcl_test && {sys.executable} setup.py bdist_wheel',
      ...         shell=1, check=1)
      >>> assert os.path.getmtime('pipcl_test/build/foo.py') <= t0
      >>> so = glob.glob('pipcl_test/build/*.so')
      >>> assert len(so) == 1
      >>> so = so[0]
      >>> assert os.path.getmtime(so) > t0
  
  Wheels and sdists
  
      Wheels:
          We generate wheels according to:
          https://packaging.python.org/specifications/binary-distribution-format/
  
          * `{name}-{version}.dist-info/RECORD` uses sha256 hashes.
          * We do not generate other `RECORD*` files such as
            `RECORD.jws` or `RECORD.p7s`.
          * `{name}-{version}.dist-info/WHEEL` has:
  
            * `Wheel-Version: 1.0`
            * `Root-Is-Purelib: false`
          * No support for signed wheels.
  
      Sdists:
          We generate sdist's according to:
          https://packaging.python.org/specifications/source-distribution-format/
class_docstr_tok: ["Our","constructor","takes","a","definition","of","a","Python","package","similar","to","that","passed","to","`","distutils.core.setup","(",")","`","or","`","setuptools.setup","(",")","`","(","name",",","version",",","summary","etc",")","plus","callbacks","for","building",",","getting","a","list","of","sdist","filenames",",","and","cleaning",".","We","provide","methods","that","can","be","used","to","implement","a","Python","package's","`","setup.py","`","supporting","PEP-517",".","We","also","support","basic","command","line","handling","for","use","with","a","legacy","(","pre-PEP-517",")","pip",",","as","implemented","by","legacy","distutils\/setuptools","and","described","in",":","https",":","\/\/pip.pypa.io\/en\/stable\/reference\/build-system\/setup-py\/","Here","is","a","`","doctest","`","example","of","using","pipcl","to","create","a","SWIG","extension","module",".","Requires","`","swig","`",".","Create","an","empty","test","directory",":",">",">",">","import","os",">",">",">","import","shutil",">",">",">","shutil.rmtree","(","'pipcl_test","'",",","ignore_errors=1",")",">",">",">","os.mkdir","(","'pipcl_test","'",")","Create","a","`","setup.py","`","which","uses","`","pipcl","`","to","define","an","extension","module",".",">",">",">","import","textwrap",">",">",">","with","open","(","'pipcl_test\/setup.py","'",",","'","w","'",")","as","f",":","...","_","=","f.write","(","textwrap.dedent","(","``","''","''","...","import","sys","...","import","pipcl","...","...","def","build","(",")",":","...","so_leaf","=","pipcl.build_extension","(","...","name","=","'foo","'",",","...","path_i","=","'foo.i","'",",","...","outdir","=","'build","'",",","...",")","...","return","[","...","(","'build\/foo.py","'",",","'foo\/__init__.py","'",")",",","...","(","f'build\/","{","so_leaf","}","'",",","f'foo\/","'",")",",","...","(","'README","'",",","'","$","dist-info\/","'",")",",","...","]","...","...","def","sdist","(",")",":","...","return","[","...","'foo.i","'",",","...","'bar.i","'",",","...","'setup.py","'",",","...","'pipcl.py","'",",","...","'wdev.py","'",",","...","'README","'",",","...","]","...","...","p","=","pipcl.Package","(","...","name","=","'foo","'",",","...","version","=","'","1.2.3","'",",","...","fn_build","=","build",",","...","fn_sdist","=","sdist",",","...",")","...","...","build_wheel","=","p.build_wheel","...","build_sdist","=","p.build_sdist","...","...","#","Handle","old-style","setup.py","command-line","usage",":","...","if","__name__","==","'__main__","'",":","...","p.handle_argv","(","sys.argv",")","...","``","''","''",")",")","Create","the","files","required","by","the","above","`","setup.py","`","-","the","SWIG","`",".i","`","input","file",",","the","README","file",",","and","copies","of","`","pipcl.py","`","and","`","wdev.py","`",".",">",">",">","with","open","(","'pipcl_test\/foo.i","'",",","'","w","'",")","as","f",":","...","_","=","f.write","(","textwrap.dedent","(","``","''","''","...","%","include","bar.i","...","%","{","...","#","include","<","stdio.h",">","...","#","include","<","string.h",">","...","int","bar","(","const","char","*","text",")","...","{","...","printf","(","``","bar","(",")",":","text",":","%","s\\\\n","''",",","text",")",";","...","int","len","=","(","int",")","strlen","(","text",")",";","...","printf","(","``","bar","(",")",":","len=","%","i\\\\n","''",",","len",")",";","...","fflush","(","stdout",")",";","...","return","len",";","...","}","...","%","}","...","int","bar","(","const","char","*","text",")",";","...","``","''","''",")",")",">",">",">","with","open","(","'pipcl_test\/bar.i","'",",","'","w","'",")","as","f",":","...","_","=","f.write","(","'\\n","'",")",">",">",">","with","open","(","'pipcl_test\/README","'",",","'","w","'",")","as","f",":","...","_","=","f.write","(","textwrap.dedent","(","``","''","''","...","This","is","Foo",".","...","``","''","''",")",")",">",">",">","root","=","os.path.dirname","(","__file__",")",">",">",">","_","=","shutil.copy2","(","f","'","{","root","}","\/pipcl.py","'",",","'pipcl_test\/pipcl.py","'",")",">",">",">","_","=","shutil.copy2","(","f","'","{","root","}","\/wdev.py","'",",","'pipcl_test\/wdev.py","'",")","Use","`","setup.py","`","'s","command-line","interface","to","build","and","install","the","extension","module","into","root","`","pipcl_test\/install","`",".",">",">",">","_","=","subprocess.run","(","...","f'cd","pipcl_test","&","&","{","sys.executable","}","setup.py","--","root","install","install","'",",","...","shell=1",",","check=1",")","The","actual","install","directory","depends","on","`","sysconfig.get_path","(","'platlib","'",")","`",":",">",">",">","if","windows","(",")",":","...","install_dir","=","'pipcl_test\/install'","...","else",":","...","install_dir","=","f'pipcl_test\/install\/","{","sysconfig.get_path","(","``","platlib","''",")",".lstrip","(","os.sep",")","}","'",">",">",">","assert","os.path.isfile","(","f","'","{","install_dir","}","\/foo\/__init__.py","'",")","Create","a","test","script","which","asserts","that","Python","function","call","`","foo.bar","(","s",")","`","returns","the","length","of","`","s","`",",","and","run","it","with","`","PYTHONPATH","`","set","to","the","install","directory",":",">",">",">","with","open","(","'pipcl_test\/test.py","'",",","'","w","'",")","as","f",":","...","_","=","f.write","(","textwrap.dedent","(","``","''","''","...","import","sys","...","import","foo","...","text","=","'hello'","...","print","(","f'test.py",":","calling","foo.bar","(",")","with","text=","{","text","!","r","}","'",")","...","sys.stdout.flush","(",")","...","l","=","foo.bar","(","text",")","...","print","(","f'test.py",":","foo.bar","(",")","returned",":","{","l","}","'",")","...","assert","l","==","len","(","text",")","...","``","''","''",")",")",">",">",">","r","=","subprocess.run","(","...","f","'","{","sys.executable","}","pipcl_test\/test.py","'",",","...","shell=1",",","check=1",",","text=1",",","...","stdout=subprocess.PIPE",",","stderr=subprocess.STDOUT",",","...","env=os.environ","|","dict","(","PYTHONPATH=install_dir",")",",","...",")",">",">",">","print","(","r.stdout",")","test.py",":","calling","foo.bar","(",")","with","text='hello'","bar","(",")",":","text",":","hello","bar","(",")",":","len=5","test.py",":","foo.bar","(",")","returned",":","5","<","BLANKLINE",">","Check","that","building","sdist","and","wheel","succeeds",".","For","now","we","do","n't","attempt","to","check","that","the","sdist","and","wheel","actually","work",".",">",">",">","_","=","subprocess.run","(","...","f'cd","pipcl_test","&","&","{","sys.executable","}","setup.py","sdist","'",",","...","shell=1",",","check=1",")",">",">",">","_","=","subprocess.run","(","...","f'cd","pipcl_test","&","&","{","sys.executable","}","setup.py","bdist_wheel","'",",","...","shell=1",",","check=1",")","Check","that","rebuild","does","nothing",".",">",">",">","t0","=","os.path.getmtime","(","'pipcl_test\/build\/foo.py","'",")",">",">",">","_","=","subprocess.run","(","...","f'cd","pipcl_test","&","&","{","sys.executable","}","setup.py","bdist_wheel","'",",","...","shell=1",",","check=1",")",">",">",">","t","=","os.path.getmtime","(","'pipcl_test\/build\/foo.py","'",")",">",">",">","assert","t","==","t0","Check","that","touching","bar.i","forces","rebuild",".",">",">",">","os.utime","(","'pipcl_test\/bar.i","'",")",">",">",">","_","=","subprocess.run","(","...","f'cd","pipcl_test","&","&","{","sys.executable","}","setup.py","bdist_wheel","'",",","...","shell=1",",","check=1",")",">",">",">","t","=","os.path.getmtime","(","'pipcl_test\/build\/foo.py","'",")",">",">",">","assert","t",">","t0","Check","that","touching","foo.i.cpp","does","not","run","swig",",","but","does","recompile\/link",".",">",">",">","t0","=","time.time","(",")",">",">",">","os.utime","(","'pipcl_test\/build\/foo.i.cpp","'",")",">",">",">","_","=","subprocess.run","(","...","f'cd","pipcl_test","&","&","{","sys.executable","}","setup.py","bdist_wheel","'",",","...","shell=1",",","check=1",")",">",">",">","assert","os.path.getmtime","(","'pipcl_test\/build\/foo.py","'",")","<","=","t0",">",">",">","so","=","glob.glob","(","'pipcl_test\/build\/","*",".so","'",")",">",">",">","assert","len","(","so",")","==","1",">",">",">","so","=","so","[","0","]",">",">",">","assert","os.path.getmtime","(","so",")",">","t0","Wheels","and","sdists","Wheels",":","We","generate","wheels","according","to",":","https",":","\/\/packaging.python.org\/specifications\/binary-distribution-format\/","*","`","{","name","}","-","{","version","}",".dist-info\/RECORD","`","uses","sha256","hashes",".","*","We","do","not","generate","other","`","RECORD","*","`","files","such","as","`","RECORD.jws","`","or","`","RECORD.p7s","`",".","*","`","{","name","}","-","{","version","}",".dist-info\/WHEEL","`","has",":","*","`","Wheel-Version",":","1.0","`","*","`","Root-Is-Purelib",":","false","`","*","No","support","for","signed","wheels",".","Sdists",":","We","generate","sdist","'s","according","to",":","https",":","\/\/packaging.python.org\/specifications\/source-distribution-format\/"]
docstr: The initial args before `root` define the package
  metadata and closely follow the definitions in:
  https://packaging.python.org/specifications/core-metadata/
  
  Args:
  
      name:
          A string, the name of the Python package.
      version:
          A string, the version of the Python package. Also see PEP-440
          `Version Identification and Dependency Specification`.
      platform:
          A string or list of strings.
      supported_platform:
          A string or list of strings.
      summary:
          A string, short description of the package.
      description:
          A string, a detailed description of the package.
      description_content_type:
          A string describing markup of `description` arg. For example
          `text/markdown; variant=GFM`.
      keywords:
          A string containing comma-separated keywords.
      home_page:
          URL of home page.
      download_url:
          Where this version can be downloaded from.
      author:
          Author.
      author_email:
          Author email.
      maintainer:
          Maintainer.
      maintainer_email:
          Maintainer email.
      license:
          A string containing the license text. Written into metadata
          file `COPYING`. Is also written into metadata itself if not
          multi-line.
      classifier:
          A string or list of strings. Also see:
  
          * https://pypi.org/pypi?%3Aaction=list_classifiers
          * https://pypi.org/classifiers/
  
      requires_dist:
          A string or list of strings. Also see PEP-508.
      requires_python:
          A string or list of strings.
      requires_external:
          A string or list of strings.
      project_url:
          A string or list of strings, each of the form: `{name}, {url}`.
      provides_extra:
          A string or list of strings.
  
      root:
          Root of package, defaults to current directory.
  
      fn_build:
          A function taking no args, or a single `config_settings` dict
          arg (as described in PEP-517), that builds the package.
  
          Should return a list of items; each item should be a tuple of
          two strings `(from_, to_)`, or a single string `path` which is
          treated as the tuple `(path, path)`.
  
          `from_` should be the path to a file; if a relative path it is
          assumed to be relative to `root`.
  
          `to_` identifies what the file should be called within a wheel
          or when installing. If `to_` ends with `/`, the leaf of `from_`
          is appended to it.
  
          Initial `$dist-info/` in `_to` is replaced by
          `{name}-{version}.dist-info/`; this is useful for license files
          etc.
  
          Initial `$data/` in `_to` is replaced by
          `{name}-{version}.data/`. We do not enforce particular
          subdirectories, instead it is up to `fn_build()` to specify
          specific subdirectories such as `purelib`, `headers`,
          `scripts`, `data` etc.
  
          If we are building a wheel (e.g. `python setup.py bdist_wheel`,
          or PEP-517 pip calls `self.build_wheel()`), we add file `from_`
          to the wheel archive with name `to_`.
  
          If we are installing (e.g. `install` command in
          the argv passed to `self.handle_argv()`), then
          we copy `from_` to `{sitepackages}/{to_}`, where
          `sitepackages` is the installation directory, the
          default being `sysconfig.get_path('platlib')` e.g.
          `myvenv/lib/python3.9/site-packages/`.
  
      fn_clean:
          A function taking a single arg `all_` that cleans generated
          files. `all_` is true iff `--all` is in argv.
  
          For safety and convenience, can also returns a list of
          files/directory paths to be deleted. Relative paths are
          interpreted as relative to `root`. All paths are asserted to be
          within `root`.
  
      fn_sdist:
          A function taking no args, or a single `config_settings` dict
          arg (as described in PEP517), that returns a list of paths for
          files that should be copied into the sdist. Each item in the
          list can also be a tuple `(from_, to_)`, where `from_` is the
          path of a file and `to_` is its name within the sdist.
  
          Relative paths are interpreted as relative to `root`. It is an
          error if a path does not exist or is not a file.
  
          It can be convenient to use `pipcl.git_items()`.
  
          The specification for sdists requires that the list contains
          `pyproject.toml`; we enforce this with a diagnostic rather than
          raising an exception, to allow legacy command-line usage.
  
      tag_python:
          First element of wheel tag defined in PEP-425. If None we use
          `cp{version}`.
  
          For example if code works with any Python version, one can use
          'py3'.
  
      tag_abi:
          Second element of wheel tag defined in PEP-425. If None we use
          `none`.
  
      tag_platform:
          Third element of wheel tag defined in PEP-425. Default is
          `os.environ('AUDITWHEEL_PLAT')` if set, otherwise derived
          from `setuptools.distutils.util.get_platform()` (was
          `distutils.util.get_platform()` as specified in the PEP), e.g.
          `openbsd_7_0_amd64`.
  
          For pure python packages use: `tag_platform=any`
  
      wheel_compression:
          Used as `zipfile.ZipFile()`'s `compression` parameter when
          creating wheels.
  
      wheel_compresslevel:
          Used as `zipfile.ZipFile()`'s `compresslevel` parameter when
          creating wheels.
docstr_tok: ["The","initial","args","before","`","root","`","define","the","package","metadata","and","closely","follow","the","definitions","in",":","https",":","\/\/packaging.python.org\/specifications\/core-metadata\/","Args",":","name",":","A","string",",","the","name","of","the","Python","package",".","version",":","A","string",",","the","version","of","the","Python","package",".","Also","see","PEP-440","`","Version","Identification","and","Dependency","Specification","`",".","platform",":","A","string","or","list","of","strings",".","supported_platform",":","A","string","or","list","of","strings",".","summary",":","A","string",",","short","description","of","the","package",".","description",":","A","string",",","a","detailed","description","of","the","package",".","description_content_type",":","A","string","describing","markup","of","`","description","`","arg",".","For","example","`","text\/markdown",";","variant=GFM","`",".","keywords",":","A","string","containing","comma-separated","keywords",".","home_page",":","URL","of","home","page",".","download_url",":","Where","this","version","can","be","downloaded","from",".","author",":","Author",".","author_email",":","Author","email",".","maintainer",":","Maintainer",".","maintainer_email",":","Maintainer","email",".","license",":","A","string","containing","the","license","text",".","Written","into","metadata","file","`","COPYING","`",".","Is","also","written","into","metadata","itself","if","not","multi-line",".","classifier",":","A","string","or","list","of","strings",".","Also","see",":","*","https",":","\/\/pypi.org\/pypi","?","%","3Aaction=list_classifiers","*","https",":","\/\/pypi.org\/classifiers\/","requires_dist",":","A","string","or","list","of","strings",".","Also","see","PEP-508",".","requires_python",":","A","string","or","list","of","strings",".","requires_external",":","A","string","or","list","of","strings",".","project_url",":","A","string","or","list","of","strings",",","each","of","the","form",":","`","{","name","}",",","{","url","}","`",".","provides_extra",":","A","string","or","list","of","strings",".","root",":","Root","of","package",",","defaults","to","current","directory",".","fn_build",":","A","function","taking","no","args",",","or","a","single","`","config_settings","`","dict","arg","(","as","described","in","PEP-517",")",",","that","builds","the","package",".","Should","return","a","list","of","items",";","each","item","should","be","a","tuple","of","two","strings","`","(","from_",",","to_",")","`",",","or","a","single","string","`","path","`","which","is","treated","as","the","tuple","`","(","path",",","path",")","`",".","`","from_","`","should","be","the","path","to","a","file",";","if","a","relative","path","it","is","assumed","to","be","relative","to","`","root","`",".","`","to_","`","identifies","what","the","file","should","be","called","within","a","wheel","or","when","installing",".","If","`","to_","`","ends","with","`","\/","`",",","the","leaf","of","`","from_","`","is","appended","to","it",".","Initial","`","$","dist-info\/","`","in","`","_to","`","is","replaced","by","`","{","name","}","-","{","version","}",".dist-info\/","`",";","this","is","useful","for","license","files","etc",".","Initial","`","$","data\/","`","in","`","_to","`","is","replaced","by","`","{","name","}","-","{","version","}",".data\/","`",".","We","do","not","enforce","particular","subdirectories",",","instead","it","is","up","to","`","fn_build","(",")","`","to","specify","specific","subdirectories","such","as","`","purelib","`",",","`","headers","`",",","`","scripts","`",",","`","data","`","etc",".","If","we","are","building","a","wheel","(","e.g",".","`","python","setup.py","bdist_wheel","`",",","or","PEP-517","pip","calls","`","self.build_wheel","(",")","`",")",",","we","add","file","`","from_","`","to","the","wheel","archive","with","name","`","to_","`",".","If","we","are","installing","(","e.g",".","`","install","`","command","in","the","argv","passed","to","`","self.handle_argv","(",")","`",")",",","then","we","copy","`","from_","`","to","`","{","sitepackages","}","\/","{","to_","}","`",",","where","`","sitepackages","`","is","the","installation","directory",",","the","default","being","`","sysconfig.get_path","(","'platlib","'",")","`","e.g",".","`","myvenv\/lib\/python3.9\/site-packages\/","`",".","fn_clean",":","A","function","taking","a","single","arg","`","all_","`","that","cleans","generated","files",".","`","all_","`","is","true","iff","`","--","all","`","is","in","argv",".","For","safety","and","convenience",",","can","also","returns","a","list","of","files\/directory","paths","to","be","deleted",".","Relative","paths","are","interpreted","as","relative","to","`","root","`",".","All","paths","are","asserted","to","be","within","`","root","`",".","fn_sdist",":","A","function","taking","no","args",",","or","a","single","`","config_settings","`","dict","arg","(","as","described","in","PEP517",")",",","that","returns","a","list","of","paths","for","files","that","should","be","copied","into","the","sdist",".","Each","item","in","the","list","can","also","be","a","tuple","`","(","from_",",","to_",")","`",",","where","`","from_","`","is","the","path","of","a","file","and","`","to_","`","is","its","name","within","the","sdist",".","Relative","paths","are","interpreted","as","relative","to","`","root","`",".","It","is","an","error","if","a","path","does","not","exist","or","is","not","a","file",".","It","can","be","convenient","to","use","`","pipcl.git_items","(",")","`",".","The","specification","for","sdists","requires","that","the","list","contains","`","pyproject.toml","`",";","we","enforce","this","with","a","diagnostic","rather","than","raising","an","exception",",","to","allow","legacy","command-line","usage",".","tag_python",":","First","element","of","wheel","tag","defined","in","PEP-425",".","If","None","we","use","`","cp","{","version","}","`",".","For","example","if","code","works","with","any","Python","version",",","one","can","use","'py3","'",".","tag_abi",":","Second","element","of","wheel","tag","defined","in","PEP-425",".","If","None","we","use","`","none","`",".","tag_platform",":","Third","element","of","wheel","tag","defined","in","PEP-425",".","Default","is","`","os.environ","(","'AUDITWHEEL_PLAT","'",")","`","if","set",",","otherwise","derived","from","`","setuptools.distutils.util.get_platform","(",")","`","(","was","`","distutils.util.get_platform","(",")","`","as","specified","in","the","PEP",")",",","e.g",".","`","openbsd_7_0_amd64","`",".","For","pure","python","packages","use",":","`","tag_platform=any","`","wheel_compression",":","Used","as","`","zipfile.ZipFile","(",")","`","'s","`","compression","`","parameter","when","creating","wheels",".","wheel_compresslevel",":","Used","as","`","zipfile.ZipFile","(",")","`","'s","`","compresslevel","`","parameter","when","creating","wheels","."]
code: def __init__(
      self,
      name,
      version,
      platform=None,
      supported_platform=None,
      summary=None,
      description=None,
      description_content_type=None,
      keywords=None,
      home_page=None,
      download_url=None,
      author=None,
      author_email=None,
      maintainer=None,
      maintainer_email=None,
      license=None,
      classifier=None,
      requires_dist=None,
      requires_python=None,
      requires_external=None,
      project_url=None,
      provides_extra=None,
      root=None,
      fn_build=None,
      fn_clean=None,
      fn_sdist=None,
      tag_python=None,
      tag_abi=None,
      tag_platform=None,
      wheel_compression=zipfile.ZIP_DEFLATED,
      wheel_compresslevel=None,
  ):
      """
      The initial args before `root` define the package
      metadata and closely follow the definitions in:
      https://packaging.python.org/specifications/core-metadata/
  
      Args:
  
          name:
              A string, the name of the Python package.
          version:
              A string, the version of the Python package. Also see PEP-440
              `Version Identification and Dependency Specification`.
          platform:
              A string or list of strings.
          supported_platform:
              A string or list of strings.
          summary:
              A string, short description of the package.
          description:
              A string, a detailed description of the package.
          description_content_type:
              A string describing markup of `description` arg. For example
              `text/markdown; variant=GFM`.
          keywords:
              A string containing comma-separated keywords.
          home_page:
              URL of home page.
          download_url:
              Where this version can be downloaded from.
          author:
              Author.
          author_email:
              Author email.
          maintainer:
              Maintainer.
          maintainer_email:
              Maintainer email.
          license:
              A string containing the license text. Written into metadata
              file `COPYING`. Is also written into metadata itself if not
              multi-line.
          classifier:
              A string or list of strings. Also see:
  
              * https://pypi.org/pypi?%3Aaction=list_classifiers
              * https://pypi.org/classifiers/
  
          requires_dist:
              A string or list of strings. Also see PEP-508.
          requires_python:
              A string or list of strings.
          requires_external:
              A string or list of strings.
          project_url:
              A string or list of strings, each of the form: `{name}, {url}`.
          provides_extra:
              A string or list of strings.
  
          root:
              Root of package, defaults to current directory.
  
          fn_build:
              A function taking no args, or a single `config_settings` dict
              arg (as described in PEP-517), that builds the package.
  
              Should return a list of items; each item should be a tuple of
              two strings `(from_, to_)`, or a single string `path` which is
              treated as the tuple `(path, path)`.
  
              `from_` should be the path to a file; if a relative path it is
              assumed to be relative to `root`.
  
              `to_` identifies what the file should be called within a wheel
              or when installing. If `to_` ends with `/`, the leaf of `from_`
              is appended to it.
  
              Initial `$dist-info/` in `_to` is replaced by
              `{name}-{version}.dist-info/`; this is useful for license files
              etc.
  
              Initial `$data/` in `_to` is replaced by
              `{name}-{version}.data/`. We do not enforce particular
              subdirectories, instead it is up to `fn_build()` to specify
              specific subdirectories such as `purelib`, `headers`,
              `scripts`, `data` etc.
  
              If we are building a wheel (e.g. `python setup.py bdist_wheel`,
              or PEP-517 pip calls `self.build_wheel()`), we add file `from_`
              to the wheel archive with name `to_`.
  
              If we are installing (e.g. `install` command in
              the argv passed to `self.handle_argv()`), then
              we copy `from_` to `{sitepackages}/{to_}`, where
              `sitepackages` is the installation directory, the
              default being `sysconfig.get_path('platlib')` e.g.
              `myvenv/lib/python3.9/site-packages/`.
  
          fn_clean:
              A function taking a single arg `all_` that cleans generated
              files. `all_` is true iff `--all` is in argv.
  
              For safety and convenience, can also returns a list of
              files/directory paths to be deleted. Relative paths are
              interpreted as relative to `root`. All paths are asserted to be
              within `root`.
  
          fn_sdist:
              A function taking no args, or a single `config_settings` dict
              arg (as described in PEP517), that returns a list of paths for
              files that should be copied into the sdist. Each item in the
              list can also be a tuple `(from_, to_)`, where `from_` is the
              path of a file and `to_` is its name within the sdist.
  
              Relative paths are interpreted as relative to `root`. It is an
              error if a path does not exist or is not a file.
  
              It can be convenient to use `pipcl.git_items()`.
  
              The specification for sdists requires that the list contains
              `pyproject.toml`; we enforce this with a diagnostic rather than
              raising an exception, to allow legacy command-line usage.
  
          tag_python:
              First element of wheel tag defined in PEP-425. If None we use
              `cp{version}`.
  
              For example if code works with any Python version, one can use
              'py3'.
  
          tag_abi:
              Second element of wheel tag defined in PEP-425. If None we use
              `none`.
  
          tag_platform:
              Third element of wheel tag defined in PEP-425. Default is
              `os.environ('AUDITWHEEL_PLAT')` if set, otherwise derived
              from `setuptools.distutils.util.get_platform()` (was
              `distutils.util.get_platform()` as specified in the PEP), e.g.
              `openbsd_7_0_amd64`.
  
              For pure python packages use: `tag_platform=any`
  
          wheel_compression:
              Used as `zipfile.ZipFile()`'s `compression` parameter when
              creating wheels.
  
          wheel_compresslevel:
              Used as `zipfile.ZipFile()`'s `compresslevel` parameter when
              creating wheels.
  
      """
      assert name
      assert version
  
      def assert_str(v):
          if v is not None:
              assert isinstance(v, str), f"Not a string: {v!r}"
  
      def assert_str_or_multi(v):
          if v is not None:
              assert isinstance(
                  v, (str, tuple, list)
              ), f"Not a string, tuple or list: {v!r}"
  
      assert_str(name)
      assert_str(version)
      assert_str_or_multi(platform)
      assert_str_or_multi(supported_platform)
      assert_str(summary)
      assert_str(description)
      assert_str(description_content_type)
      assert_str(keywords)
      assert_str(home_page)
      assert_str(download_url)
      assert_str(author)
      assert_str(author_email)
      assert_str(maintainer)
      assert_str(maintainer_email)
      assert_str(license)
      assert_str_or_multi(classifier)
      assert_str_or_multi(requires_dist)
      assert_str(requires_python)
      assert_str_or_multi(requires_external)
      assert_str_or_multi(project_url)
      assert_str_or_multi(provides_extra)
  
      # https://packaging.python.org/en/latest/specifications/core-metadata/.
      assert re.match(
          "([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$",
          name,
          re.IGNORECASE,
      ), f"Bad name: {name!r}"
  
      # PEP-440.
      assert re.match(
          r"^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$",
          version,
      ), f"Bad version: {version!r}."
  
      # https://packaging.python.org/en/latest/specifications/binary-distribution-format/
      if tag_python:
          assert "-" not in tag_python
      if tag_abi:
          assert "-" not in tag_abi
      if tag_platform:
          assert "-" not in tag_platform
  
      self.name = name
      self.version = version
      self.platform = platform
      self.supported_platform = supported_platform
      self.summary = summary
      self.description = description
      self.description_content_type = description_content_type
      self.keywords = keywords
      self.home_page = home_page
      self.download_url = download_url
      self.author = author
      self.author_email = author_email
      self.maintainer = maintainer
      self.maintainer_email = maintainer_email
      self.license = license
      self.classifier = classifier
      self.requires_dist = requires_dist
      self.requires_python = requires_python
      self.requires_external = requires_external
      self.project_url = project_url
      self.provides_extra = provides_extra
  
      self.root = os.path.abspath(root if root else os.getcwd())
      self.fn_build = fn_build
      self.fn_clean = fn_clean
      self.fn_sdist = fn_sdist
      self.tag_python = tag_python
      self.tag_abi = tag_abi
      self.tag_platform = tag_platform
  
      self.wheel_compression = wheel_compression
      self.wheel_compresslevel = wheel_compresslevel
  
imports: import base64
  import glob
  import hashlib
  import inspect
  import io
  import os
  import platform
  import re
  import shutil
  import site
  import setuptools
  import subprocess
  import sys
  import sysconfig
  import tarfile
  import textwrap
  import time
  import zipfile
  import wdev
label_desc: Use image node_id 1 to create a new Package object  with example: obj = Package(name, version, platform, supported_platform, summary, description, description_content_type, keywords, home_page, download_url, author, author_email, maintainer, maintainer_email, license, classifier, requires_dist, requires_python, requires_external, project_url, provides_extra, root, fn_build, fn_clean, fn_sdist, tag_python, tag_abi, tag_platform, wheel_compression, wheel_compresslevel)