From 8dcb5c1e90a028d7b218c1ceb4e100ee9843e2e7 Mon Sep 17 00:00:00 2001 From: Brian Stack Date: Tue, 22 May 2018 16:03:59 -0700 Subject: [PATCH] Add python support --- .gitignore | 105 +++++++++++++++++++++++++++++++++++ .taskcluster.yml | 54 ++++++++++++++++++ MANIFEST.in | 4 ++ setup.cfg | 2 + setup.py | 27 +++++++++ taskcluster_urls/__init__.py | 53 ++++++++++++++++++ test/__init__.py | 0 test/basic_test.py | 30 ++++++++++ tox.ini | 11 ++++ 9 files changed, 286 insertions(+) create mode 100644 MANIFEST.in create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 taskcluster_urls/__init__.py create mode 100644 test/__init__.py create mode 100644 test/basic_test.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 312e058..f30e142 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,108 @@ jspm_packages # Optional REPL history .node_repl_history + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/.taskcluster.yml b/.taskcluster.yml index 0cc76c8..911ae2c 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -91,3 +91,57 @@ tasks: description: Run library test suite - golang 1.10 owner: '{{ event.head.user.email }}' source: '{{ event.head.repo.url }}' + - provisionerId: '{{ taskcluster.docker.provisionerId }}' + workerType: '{{ taskcluster.docker.workerType }}' + extra: + github: + events: + - pull_request.opened + - pull_request.synchronize + - pull_request.reopened + - push + payload: + maxRunTime: 3600 + image: 'python:2.7' + command: + - /bin/bash + - '-c' + - >- + git clone {{event.head.repo.url}} repo && + cd repo && + git config advice.detachedHead false && + git checkout {{event.head.sha}} && + pip install tox && + tox -e py27 + metadata: + name: taskcluster-lib-urls python 2.7 test + description: Run library test suite - python2.7 + owner: '{{ event.head.user.email }}' + source: '{{ event.head.repo.url }}' + - provisionerId: '{{ taskcluster.docker.provisionerId }}' + workerType: '{{ taskcluster.docker.workerType }}' + extra: + github: + events: + - pull_request.opened + - pull_request.synchronize + - pull_request.reopened + - push + payload: + maxRunTime: 3600 + image: 'python:3.6' + command: + - /bin/bash + - '-c' + - >- + git clone {{event.head.repo.url}} repo && + cd repo && + git config advice.detachedHead false && + git checkout {{event.head.sha}} && + pip install tox && + tox -e py36 + metadata: + name: taskcluster-lib-urls python 3.6 test + description: Run library test suite - python3.6 + owner: '{{ event.head.user.email }}' + source: '{{ event.head.repo.url }}' diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..2451f52 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include LICENSE +global-exclude *.py[co] +include specification.yml +include package.json diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..972cab3 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[tools:pytest] +flake8-max-line-length = 120 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..cfbb526 --- /dev/null +++ b/setup.py @@ -0,0 +1,27 @@ +import json +import os +from setuptools import setup + +package_json = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'package.json') +with open(package_json) as f: + version = json.load(f)['version'] + +setup( + name='taskcluster-urls', + description='Standardized url generator for taskcluster resources.', + long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), + url='https://github.com/taskcluster/taskcluster-lib-urls', + version=version, + packages=['taskcluster_urls'], + author='Brian Stack', + author_email='bstack@mozilla.com', + license='MPL2', + classifiers=[ + 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + ], +) diff --git a/taskcluster_urls/__init__.py b/taskcluster_urls/__init__.py new file mode 100644 index 0000000..c1ddd94 --- /dev/null +++ b/taskcluster_urls/__init__.py @@ -0,0 +1,53 @@ +OLD_ROOT_URL = 'https://taskcluster.net' + +def api(root_url, service, version, path): + """Generate URL for path in a Taskcluster service.""" + root_url = root_url.rstrip('/') + path = path.lstrip('/') + if root_url == OLD_ROOT_URL: + return 'https://{}.taskcluster.net/{}/{}'.format(service, version, path) + else: + return '{}/api/{}/{}/{}'.format(root_url, service, version, path) + +def apiReference(root_url, service, version): + """Generate URL for a Taskcluster api reference.""" + root_url = root_url.rstrip('/') + if root_url == OLD_ROOT_URL: + return 'https://references.taskcluster.net/{}/{}/api.json'.format(service, version) + else: + return '{}/references/{}/{}/api.json'.format(root_url, service, version) + +def docs(root_url, path): + """Generate URL for path in the Taskcluster docs.""" + root_url = root_url.rstrip('/') + path = path.lstrip('/') + if root_url == OLD_ROOT_URL: + return 'https://docs.taskcluster.net/{}'.format(path) + else: + return '{}/docs/{}'.format(root_url, path) + +def exchangeReference(root_url, service, version): + """Generate URL for a Taskcluster exchange reference.""" + root_url = root_url.rstrip('/') + if root_url == OLD_ROOT_URL: + return 'https://references.taskcluster.net/{}/{}/exchanges.json'.format(service, version) + else: + return '{}/references/{}/{}/exchanges.json'.format(root_url, service, version) + +def schema(root_url, service, name): + """Generate URL for a schema in a Taskcluster service.""" + root_url = root_url.rstrip('/') + name = name.lstrip('/') + if root_url == OLD_ROOT_URL: + return 'https://schemas.taskcluster.net/{}/{}'.format(service, name) + else: + return '{}/schemas/{}/{}'.format(root_url, service, name) + +def ui(root_url, path): + """Generate URL for a path in the Taskcluster ui.""" + root_url = root_url.rstrip('/') + path = path.lstrip('/') + if root_url == OLD_ROOT_URL: + return 'https://tools.taskcluster.net/{}'.format(path) + else: + return '{}/{}'.format(root_url, path) diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/basic_test.py b/test/basic_test.py new file mode 100644 index 0000000..b768153 --- /dev/null +++ b/test/basic_test.py @@ -0,0 +1,30 @@ +import os + +import yaml + +import taskcluster_urls as t + + +SPEC_FILE = os.path.join(os.path.dirname(__file__), '..', 'specification.yml') +OLD_ROOT_URL = 'https://taskcluster.net' +ROOT_URL = 'https://taskcluster.example.com' + + +def pytest_generate_tests(metafunc): + with open(SPEC_FILE) as f: + specs = yaml.load(f)['specs'] + metafunc.parametrize( + ['func', 'args', 'expected_url', 'old_expected_url'], + [(getattr(t, s['type']), + a, s['expectedUrl'], s['oldExpectedUrl']) + for s in specs + for a in s['argSets'] + ] + ) + + +def test_basic(func, args, expected_url, old_expected_url): + assert func(ROOT_URL + '/', *args) == expected_url + assert func(ROOT_URL, *args) == expected_url + assert func(OLD_ROOT_URL + '/', *args) == old_expected_url + assert func(OLD_ROOT_URL, *args) == old_expected_url diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..dd2dc18 --- /dev/null +++ b/tox.ini @@ -0,0 +1,11 @@ +[tox] +envlist = py27,py36 + +[testenv] +deps = + pyyaml + pytest + pytest-cov + pytest-flake8 +commands = + pytest -v --flake8 --cov=taskcluster_urls {posargs:test}