#hide # default_exp conda #export from fastcore.script import * from fastcore.all import * from fastrelease.core import find_config import yaml,subprocess from copy import deepcopy try: from packaging.version import parse except ImportError: from pip._vendor.packaging.version import parse _PYPI_URL = 'https://pypi.org/pypi/' #export def pypi_json(s): "Dictionary decoded JSON for PYPI path `s`" return urljson(f'{_PYPI_URL}{s}/json') #export def latest_pypi(name): "Latest version of `name` on pypi" return max(parse(r) for r,o in pypi_json(name)['releases'].items() if not parse(r).is_prerelease and not o[0]['yanked']) #export def _pip_conda_meta(name, path): ver = str(latest_pypi('sentencepiece')) pypi = pypi_json(f'{name}/{ver}') info = pypi['info'] rel = [o for o in pypi['urls'] if o['packagetype']=='sdist'][0] reqs = ['pip', 'python', 'packaging'] # Work around conda build bug - 'package' and 'source' must be first d1 = { 'package': {'name': name, 'version': ver}, 'source': {'url':rel['url'], 'sha256':rel['digests']['sha256']} } d2 = { 'build': {'number': '0', 'noarch': 'python', 'script': '{{ PYTHON }} -m pip install . -vv'}, 'test': {'imports': [name]}, 'requirements': {'host':reqs, 'run':reqs}, 'about': {'license': info['license'], 'home': info['project_url'], 'summary': info['summary']} } return d1,d2 #export def _write_yaml(path, name, d1, d2): path = Path(path) p = path/name p.mkdir(exist_ok=True, parents=True) yaml.SafeDumper.ignore_aliases = lambda *args : True with (p/'meta.yaml').open('w') as f: yaml.safe_dump(d1, f) yaml.safe_dump(d2, f) #export def write_pip_conda_meta(name, path='conda'): "Writes a `meta.yaml` file for `name` to the `conda` directory of the current directory" _write_yaml(path, name, *_pip_conda_meta(name)) #export def _get_conda_meta(): cfg,cfg_path = find_config() name,ver = cfg.get('lib_name'),cfg.get('version') url = cfg.get('doc_host') or cfg.get('git_url') reqs = ['pip', 'python', 'packaging'] if cfg.get('requirements'): reqs += cfg.get('requirements').split() if cfg.get('conda_requirements'): reqs += cfg.get('conda_requirements').split() pypi = pypi_json(f'{name}/{ver}') rel = [o for o in pypi['urls'] if o['packagetype']=='sdist'][0] # Work around conda build bug - 'package' and 'source' must be first d1 = { 'package': {'name': name, 'version': ver}, 'source': {'url':rel['url'], 'sha256':rel['digests']['sha256']} } d2 = { 'build': {'number': '0', 'noarch': 'python', 'script': '{{ PYTHON }} -m pip install . -vv'}, 'requirements': {'host':reqs, 'run':reqs}, 'test': {'imports': [cfg.get('lib_path')]}, 'about': { 'license': 'Apache Software', 'license_family': 'APACHE', 'home': url, 'doc_url': url, 'dev_url': url, 'summary': cfg.get('description') }, 'extra': {'recipe-maintainers': [cfg.get('user')]} } return name,d1,d2 #export def write_conda_meta(path='conda'): "Writes a `meta.yaml` file to the `conda` directory of the current directory" _write_yaml(path, *_get_conda_meta()) #export @call_parse def fastrelease_conda_package(path:Param("Path where package will be created", str)='conda', do_build:Param("Run `conda build` step", bool_arg)=True, build_args:Param("Additional args (as str) to send to `conda build`", str)='', do_upload:Param("Run `anaconda upload` step", bool_arg)=True, upload_user:Param("Optional user to upload package to")=None): "Create a `meta.yaml` file ready to be built into a package, and optionally build and upload it" write_conda_meta(path) cfg,cfg_path = find_config() out = f"Done. Next steps:\n```\`cd {path}\n""" name,lib_path = cfg.get('lib_name'),cfg.get('lib_path') out_upl = f"anaconda upload build/noarch/{lib_path}-{cfg.get('version')}-py_0.tar.bz2" if not do_build: print(f"{out}conda build .\n{out_upl}\n```") return os.chdir(path) res = run(f"conda build --output-folder build {build_args} {name}") if 'anaconda upload' not in res: print(f"{res}\n\Build failed.") return upload_str = re.findall('(anaconda upload .*)', res)[0] if upload_user: upload_str = upload_str.replace('anaconda upload ', f'anaconda upload -u {upload_user} ') res = run(upload_str) #hide from nbdev.export import notebook2script notebook2script()