diff --git a/.arclint b/.arclint --- a/.arclint +++ b/.arclint @@ -19,8 +19,7 @@ "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)", - "(^contrib/apple-sdk-tools/)", - "(^contrib/buildbot/python_phabricator/)" + "(^contrib/apple-sdk-tools/)" ], "flags": [ "--aggressive", @@ -33,8 +32,7 @@ "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)", - "(^contrib/apple-sdk-tools/)", - "(^contrib/buildbot/python_phabricator/)" + "(^contrib/apple-sdk-tools/)" ], "flags": [ "--ignore=E501,E704,W503,W504" @@ -63,8 +61,7 @@ "exclude": [ "(^test/lint/lint-python-format\\.py$)", "(^contrib/gitian-builder/)", - "(^contrib/apple-sdk-tools/)", - "(^contrib/buildbot/python_phabricator/)" + "(^contrib/apple-sdk-tools/)" ] }, "phpcs": { @@ -168,8 +165,7 @@ "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)", - "(^contrib/apple-sdk-tools/)", - "(^contrib/buildbot/python_phabricator/)" + "(^contrib/apple-sdk-tools/)" ] }, "lint-python-shebang": { @@ -178,8 +174,7 @@ "exclude": [ "(__init__\\.py$)", "(^contrib/gitian-builder/)", - "(^contrib/apple-sdk-tools/)", - "(^contrib/buildbot/python_phabricator/)" + "(^contrib/apple-sdk-tools/)" ] }, "lint-bash-shebang": { @@ -258,10 +253,7 @@ }, "yamllint": { "type": "yamllint", - "include": "(\\.(yml|yaml)$)", - "exclude": [ - "(^contrib/buildbot/python_phabricator/)" - ] + "include": "(\\.(yml|yaml)$)" }, "lint-check-nonfatal": { "type": "lint-check-nonfatal", @@ -291,8 +283,7 @@ "include": "(\\.py$)", "exclude": [ "(^contrib/gitian-builder/)", - "(^contrib/apple-sdk-tools/)", - "(^contrib/buildbot/python_phabricator/)" + "(^contrib/apple-sdk-tools/)" ] }, "prettier": { diff --git a/contrib/buildbot/phabricator_wrapper.py b/contrib/buildbot/phabricator_wrapper.py --- a/contrib/buildbot/phabricator_wrapper.py +++ b/contrib/buildbot/phabricator_wrapper.py @@ -10,7 +10,7 @@ from build import BuildStatus from constants import Deployment -from python_phabricator.phabricator import Phabricator +from phabricator import Phabricator BUILDNAME_IGNORE_KEYWORD = "__BOTIGNORE" diff --git a/contrib/buildbot/python_phabricator/.gitignore b/contrib/buildbot/python_phabricator/.gitignore deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.pyc -*.swp -*.egg -*.egg-info -build/ -dist/ -.idea diff --git a/contrib/buildbot/python_phabricator/.travis.yml b/contrib/buildbot/python_phabricator/.travis.yml deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: python -python: -- '2.7' -- '3.5' -install: pip install .[tests] -script: python -m phabricator.tests.test_phabricator -deploy: - provider: pypi - user: disqus - password: - secure: AJ7zSLd6BgI4W8Kp3KEx5O40bUJA91PkgLTZb5MnCx4/8nUPlkk+LqvodaiiJQEGzpP8COPvRlzJ/swd8d0P38+Se6V83wA43MylimzrgngO6t3c/lXa/aMnrRzSpSfK5QznEMP2zcSU1ReD+2dNr7ATKajbGqTzrCFk/hQPMZ0= - on: - tags: true diff --git a/contrib/buildbot/python_phabricator/CHANGES b/contrib/buildbot/python_phabricator/CHANGES deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/CHANGES +++ /dev/null @@ -1,31 +0,0 @@ -0.7.0 - -* Allow for nested methods to support conduit calls such as diffusion.repository.edit -* Fix regular expressions that cause type parsing to fail - -0.6.1 - -* Fix Python 3 related issues - -0.6.0 - -* Python 3 support -* Fix "not JSON serializable" error when not using a token -* Better tests -* Updated interfaces -* Moved `conduit` to `_conduit` so `.conduit` API is available now -* Updated interfaces to the latest Phabricator version - -0.5.0 - -* Support new style token-based authentication - -0.4.0 - -* Update interfaces.json to Phab @ e75b389 -* Add Phabricator.update_interfaces to pull latest interfaces from conduit.query -* Fix validation of string to be str or unicode - -0.1.0 - -* Initial release diff --git a/contrib/buildbot/python_phabricator/LICENSE b/contrib/buildbot/python_phabricator/LICENSE deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright 2012 DISQUS - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/contrib/buildbot/python_phabricator/MANIFEST.in b/contrib/buildbot/python_phabricator/MANIFEST.in deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include setup.py README.rst MANIFEST.in LICENSE phabricator/interfaces.json -global-exclude *~ diff --git a/contrib/buildbot/python_phabricator/README.rst b/contrib/buildbot/python_phabricator/README.rst deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/README.rst +++ /dev/null @@ -1,42 +0,0 @@ -python-phabricator -================== - -.. image:: https://travis-ci.org/disqus/python-phabricator.png?branch=master - :target: https://travis-ci.org/disqus/python-phabricator - -Installation ------------- - -:: - - $ pip install phabricator - -Usage ------ - -Use the API by instantiating it, and then calling the method through dotted notation chaining:: - - from phabricator import Phabricator - phab = Phabricator() # This will use your ~/.arcrc file - phab.user.whoami() - -You can also use:: - - phab = Phabricator(host='https://my-phabricator.org/api/', token='api-mytoken') - -Parameters are passed as keyword arguments to the resource call:: - - phab.user.find(aliases=["sugarc0de"]) - -Documentation on all methods is located at https://secure.phabricator.com/conduit/ - -Interface out-of-date ---------------------- - -If Phabricator modifies Conduit and the included ``interfaces.json`` is out-of-date or to make sure -to always have the latest interfaces:: - - from phabricator import Phabricator - phab = Phabricator() - phab.update_interfaces() - phab.user.whoami() diff --git a/contrib/buildbot/python_phabricator/phabricator/__init__.py b/contrib/buildbot/python_phabricator/phabricator/__init__.py deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/phabricator/__init__.py +++ /dev/null @@ -1,394 +0,0 @@ -""" -python-phabricator ------------------- ->>> api = phabricator.Phabricator() ->>> api.user.whoami().userName -'example' - -For more endpoints, see https://secure.phabricator.com/conduit/ - -""" -try: - __version__ = __import__('pkg_resources') \ - .get_distribution('phabricator').version -except: - __version__ = 'unknown' - -import collections -import copy -import hashlib -import json -import os.path -import re -import socket -import pkgutil -import time -import requests - -from ._compat import ( - MutableMapping, iteritems, string_types, urlencode, -) - - -__all__ = ['Phabricator'] - - -ON_WINDOWS = os.name == 'nt' -CURRENT_DIR = os.getcwd() - - -# Default Phabricator interfaces -INTERFACES = {} -INTERFACES = json.loads( - pkgutil.get_data(__name__, 'interfaces.json') - .decode('utf-8')) - - -# Load arc config -ARC_CONFIGS = ( - # System config - os.path.join( - os.environ['ProgramData'], - 'Phabricator', - 'Arcanist', - 'config' - ) if ON_WINDOWS else os.path.join('/etc', 'arcconfig'), - - # User config - os.path.join( - os.environ['AppData'] if ON_WINDOWS else os.path.expanduser('~'), - '.arcrc' - ), - - # Project config - os.path.join(CURRENT_DIR, '.arcconfig'), - - # Local project config - os.path.join(CURRENT_DIR, '.git', 'arc', 'config'), -) - -ARCRC = {} -for conf in ARC_CONFIGS: - if os.path.exists(conf): - with open(conf, 'r') as fobj: - ARCRC.update(json.load(fobj)) - - -# Map Phabricator types to Python types -PARAM_TYPE_MAP = { - # int types - 'int': int, - 'uint': int, - 'revisionid': int, - 'revision_id': int, - 'diffid': int, - 'diff_id': int, - 'id': int, - - # bool types - 'bool': bool, - - # dict types - 'map': dict, - 'dict': dict, - - # list types - 'list': list, - - # tuple types - 'pair': tuple, - - # str types - 'str': string_types, - 'string': string_types, - 'phid': string_types, - 'guids': string_types, - 'type': string_types, -} - -TYPE_INFO_COMMENT_RE = re.compile(r'\s*\([^)]+\)\s*$') -TYPE_INFO_SPLITTER_RE = re.compile(r'(\w+(?:<.+>)?)(?:\s+|$)') -TYPE_INFO_RE = re.compile(r']+>>?)?(?:.+|$)') - - -def map_param_type(param_type): - """ - Perform param type mapping - This requires a bit of logic since this isn't standardized. - If a type doesn't map, assume str - """ - main_type, sub_type = TYPE_INFO_RE.match(param_type).groups() - - if main_type in ('list', 'array'): - # Handle no sub-type: "required list" - if sub_type is not None: - sub_type = sub_type.strip() - - if not sub_type: - sub_type = 'str' - - # Handle list of pairs: "optional list>" - sub_match = TYPE_INFO_RE.match(sub_type) - if sub_match: - sub_type = sub_match.group(1).lower() - - return [PARAM_TYPE_MAP.setdefault(sub_type, string_types)] - - return PARAM_TYPE_MAP.setdefault(main_type, string_types) - - -def parse_interfaces(interfaces): - """ - Parse the conduit.query json dict response - This performs the logic of parsing the non-standard params dict - and then returning a dict Resource can understand - """ - parsed_interfaces = collections.defaultdict(dict) - - for m, d in iteritems(interfaces): - app, func = m.split('.', 1) - - method = parsed_interfaces[app][func] = {} - - # Make default assumptions since these aren't provided by Phab - method['formats'] = ['json', 'human'] - method['method'] = 'POST' - - method['optional'] = {} - method['required'] = {} - - for name, type_info in iteritems(dict(d['params'])): - # Set the defaults - optionality = 'required' - param_type = 'string' - - # Usually in the format: - type_info = TYPE_INFO_COMMENT_RE.sub('', type_info) - info_pieces = TYPE_INFO_SPLITTER_RE.findall(type_info) - for info_piece in info_pieces: - if info_piece in ('optional', 'required'): - optionality = info_piece - elif info_piece == 'ignored': - optionality = 'optional' - param_type = 'string' - elif info_piece == 'nonempty': - optionality = 'required' - elif info_piece == 'deprecated': - optionality = 'optional' - else: - param_type = info_piece - - method[optionality][name] = map_param_type(param_type) - - return dict(parsed_interfaces) - - -class ConfigurationError(Exception): - pass - - -class APIError(Exception): - def __init__(self, code, message): - self.code = code - self.message = message - - def __str__(self): - return '%s: %s' % (self.code, self.message) - - -class Result(MutableMapping): - def __init__(self, response): - self.response = response - - def __getitem__(self, key): - return self.response[key] - - __getattr__ = __getitem__ - - def __setitem__(self, key, value): - self.response[key] = value - - def __delitem__(self, key): - del self.response[key] - - def __iter__(self): - return iter(self.response) - - def __len__(self): - return len(self.response) - - def __repr__(self): - return '<%s: %s>' % (type(self).__name__, repr(self.response)) - - -class Resource(object): - def __init__(self, api, interface=None, endpoint=None, method=None, nested=False): - self.api = api - self.interface = interface or copy.deepcopy(parse_interfaces(INTERFACES)) - self.endpoint = endpoint - self.method = method - self.nested = nested - - def __getattr__(self, attr): - if attr in getattr(self, '__dict__'): - return getattr(self, attr) - interface = self.interface - if self.nested: - attr = "%s.%s" % (self.endpoint, attr) - submethod_exists = False - submethod_match = attr + '.' - for key in interface.keys(): - if key.startswith(submethod_match): - submethod_exists = True - break - if attr not in interface and submethod_exists: - return Resource(self.api, interface, attr, self.endpoint, nested=True) - elif attr not in interface: - interface[attr] = {} - if self.nested: - return Resource(self.api, interface[attr], attr, self.method) - return Resource(self.api, interface[attr], attr, self.endpoint) - - def __call__(self, **kwargs): - return self._request(**kwargs) - - def _request(self, **kwargs): - # Check for missing variables - resource = self.interface - - def validate_kwarg(key, target): - # Always allow list - if isinstance(target, list): - return ( - isinstance(key, (list, tuple, set)) and - all(validate_kwarg(x, target[0]) for x in key) - ) - - return isinstance(key, tuple(target) if isinstance(target, list) else target) - - for key, val in resource.get('required', {}).items(): - if key not in [x.split(':')[0] for x in kwargs.keys()]: - raise ValueError('Missing required argument: %s' % key) - if isinstance(kwargs.get(key), list) and not isinstance(val, list): - raise ValueError('Wrong argument type: %s is not a list' % key) - elif not validate_kwarg(kwargs.get(key), val): - if isinstance(val, list): - raise ValueError('Wrong argument type: %s is not a list of %ss' % (key, val[0])) - raise ValueError('Wrong argument type: %s is not a %s' % (key, val)) - - conduit = self.api._conduit - - if conduit: - # Already authenticated, add session key to json data - kwargs['__conduit__'] = conduit - elif self.method == 'conduit' and self.endpoint == 'connect': - # Not authenticated, requesting new session key - token = str(int(time.time())) - kwargs['authToken'] = token - kwargs['authSignature'] = self.api.generate_hash(token) - else: - # Authorization is required, silently auth the user - self.api.connect() - kwargs['__conduit__'] = self.api._conduit - - - headers = { - 'User-Agent': 'python-phabricator/%s' % str(self.api.clientVersion), - 'Content-Type': 'application/x-www-form-urlencoded' - } - - body = { - "params": json.dumps(kwargs), - "output": self.api.response_format - } - - # TODO: Use HTTP "method" from interfaces.json - path = '%s%s.%s' % (self.api.host, self.method, self.endpoint) - response = requests.post(path, data=body, headers=headers, timeout=self.api.timeout) - - # Make sure we got a 2xx response indicating success - if not response.status_code >= 200 or not response.status_code < 300: - raise requests.exceptions.HTTPError( - 'Bad response status: {0}'.format(response.status_code) - ) - - data = self._parse_response(response.text) - - return Result(data['result']) - - def _parse_response(self, data): - # Process the response back to python - parsed = self.api.formats[self.api.response_format](data) - - # Errors return 200, so check response content for exception - if parsed['error_code']: - raise APIError(parsed['error_code'], parsed['error_info']) - - return parsed - - -class Phabricator(Resource): - formats = { - 'json': lambda x: json.loads(x), - } - - def __init__(self, username=None, certificate=None, host=None, - timeout=5, response_format='json', token=None, **kwargs): - - defined_hosts = ARCRC.get('hosts', {}) - - try: - self.host = host if host else list(defined_hosts.keys())[0] - except IndexError: - raise ConfigurationError("No host found or provided.") - - current_host_config = defined_hosts.get(self.host, {}) - self.conduit_token = token if token else current_host_config.get('token') - - if self.conduit_token is None: - self.username = username if username else current_host_config.get('user') - self.certificate = certificate if certificate else current_host_config.get('cert') - - self.timeout = timeout - self.response_format = response_format - self.client = 'python-phabricator' - self.clientVersion = 1 - self.clientDescription = socket.gethostname() + ':python-phabricator' - self._conduit = None - - super(Phabricator, self).__init__(self, **kwargs) - - def _request(self, **kwargs): - raise SyntaxError('You cannot call the Conduit API without a resource.') - - def connect(self): - if self.conduit_token: - self._conduit = { - 'token': self.conduit_token - } - return - - auth = Resource(api=self, method='conduit', endpoint='connect') - - response = auth( - user=self.username, - host=self.host, - client=self.client, - clientVersion=self.clientVersion - ) - - self._conduit = { - 'sessionKey': response.sessionKey, - 'connectionID': response.connectionID - } - - def generate_hash(self, token): - source_string = (token + self.api.certificate).encode('utf-8') - return hashlib.sha1(source_string).hexdigest() - - def update_interfaces(self): - query = Resource(api=self, method='conduit', endpoint='query') - - interfaces = query() - - self.interface = parse_interfaces(interfaces) diff --git a/contrib/buildbot/python_phabricator/phabricator/_compat.py b/contrib/buildbot/python_phabricator/phabricator/_compat.py deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/phabricator/_compat.py +++ /dev/null @@ -1,26 +0,0 @@ -import sys - -PY3 = sys.version_info[0] >= 3 - -try: - from collections.abc import MutableMapping -except ImportError: - from collections import MutableMapping - -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -if PY3: - str_type = str - string_types = str, - - def iteritems(d, **kw): - return iter(d.items(**kw)) -else: - str_type = unicode - string_types = basestring, - - def iteritems(d, **kw): - return d.iteritems(**kw) diff --git a/contrib/buildbot/python_phabricator/phabricator/interfaces.json b/contrib/buildbot/python_phabricator/phabricator/interfaces.json deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/phabricator/interfaces.json +++ /dev/null @@ -1 +0,0 @@ -{"almanac.device.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"almanac.service.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"audit.query":{"description":"Query audit requests.","params":{"auditorPHIDs":"optional list\u003cphid\u003e","commitPHIDs":"optional list\u003cphid\u003e","status":"optional string-constant\u003c\"audit-status-any\", \"audit-status-open\", \"audit-status-concern\", \"audit-status-accepted\", \"audit-status-partial\"\u003e (default = \"audit-status-any\")","offset":"optional int","limit":"optional int (default = 100)"},"return":"list\u003cdict\u003e"},"auth.logout":{"description":"Terminate all web login sessions. If called via OAuth, also terminate the current OAuth token.\n\nWARNING: This method does what it claims on the label. If you call this method via the test console in the web UI, it will log you out!","params":[],"return":"void"},"auth.querypublickeys":{"description":"Query public keys.","params":{"ids":"optional list\u003cid\u003e","phids":"optional list\u003cphid\u003e","objectPHIDs":"optional list\u003cphid\u003e","keys":"optional list\u003cstring\u003e","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"result-set"},"badges.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"badges.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"conduit.connect":{"description":"Connect a session-based client.","params":{"client":"required string","clientVersion":"required int","clientDescription":"optional string","user":"optional string","authToken":"optional int","authSignature":"optional string","host":"deprecated"},"return":"dict\u003cstring, any\u003e"},"conduit.getcapabilities":{"description":"List capabilities, wire formats, and authentication protocols available on this server.","params":[],"return":"dict\u003cstring, any\u003e"},"conduit.getcertificate":{"description":"Retrieve certificate information for a user.","params":{"token":"required string","host":"required string"},"return":"dict\u003cstring, any\u003e"},"conduit.ping":{"description":"Basic ping for monitoring or a health-check.","params":[],"return":"string"},"conduit.query":{"description":"Returns the parameters of the Conduit methods.","params":[],"return":"dict\u003cdict\u003e"},"conpherence.createthread":{"description":"Create a new conpherence thread.","params":{"title":"optional string","message":"required string","participantPHIDs":"required list\u003cphids\u003e"},"return":"nonempty dict"},"conpherence.querythread":{"description":"Query for Conpherence threads for the logged in user. You can query by IDs or PHIDs for specific Conpherence threads. Otherwise, specify limit and offset to query the most recently updated Conpherences for the logged in user.","params":{"ids":"optional array\u003cint\u003e","phids":"optional array\u003cphids\u003e","limit":"optional int","offset":"optional int"},"return":"nonempty dict"},"conpherence.querytransaction":{"description":"Query for transactions for the logged in user within a specific Conpherence room. You can specify the room by ID or PHID. Otherwise, specify limit and offset to query the most recent transactions within the Conpherence room for the logged in user.","params":{"roomID":"optional int","roomPHID":"optional phid","limit":"optional int","offset":"optional int"},"return":"nonempty dict"},"conpherence.updatethread":{"description":"Update an existing conpherence room.","params":{"id":"optional int","phid":"optional phid","title":"optional string","message":"optional string","addParticipantPHIDs":"optional list\u003cphids\u003e","removeParticipantPHID":"optional phid"},"return":"bool"},"dashboard.panel.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"differential.close":{"description":"Close a Differential revision.","params":{"revisionID":"required int"},"return":"void"},"differential.createcomment":{"description":"Add a comment to a Differential revision.","params":{"revision_id":"required revisionid","message":"optional string","action":"optional string","silent":"optional bool","attach_inlines":"optional bool"},"return":"nonempty dict"},"differential.creatediff":{"description":"Create a new Differential diff.","params":{"changes":"required list\u003cdict\u003e","sourceMachine":"required string","sourcePath":"required string","branch":"required string","bookmark":"optional string","sourceControlSystem":"required string-constant\u003c\"svn\", \"git\", \"hg\"\u003e","sourceControlPath":"required string","sourceControlBaseRevision":"required string","creationMethod":"optional string","lintStatus":"required string-constant\u003c\"none\", \"skip\", \"okay\", \"warn\", \"fail\"\u003e","unitStatus":"required string-constant\u003c\"none\", \"skip\", \"okay\", \"warn\", \"fail\"\u003e","repositoryPHID":"optional phid","parentRevisionID":"deprecated","authorPHID":"deprecated","repositoryUUID":"deprecated"},"return":"nonempty dict"},"differential.createinline":{"description":"Add an inline comment to a Differential revision.","params":{"revisionID":"optional revisionid","diffID":"optional diffid","filePath":"required string","isNewFile":"required bool","lineNumber":"required int","lineLength":"optional int","content":"required string"},"return":"nonempty dict"},"differential.createrawdiff":{"description":"Create a new Differential diff from a raw diff source.","params":{"diff":"required string","repositoryPHID":"optional string","viewPolicy":"optional string"},"return":"nonempty dict"},"differential.createrevision":{"description":"Create a new Differential revision.","params":{"user":"ignored","diffid":"required diffid","fields":"required dict"},"return":"nonempty dict"},"differential.getcommitmessage":{"description":"Retrieve Differential commit messages or message templates.","params":{"revision_id":"optional revision_id","fields":"optional dict\u003cstring, wild\u003e","edit":"optional string-constant\u003c\"edit\", \"create\"\u003e"},"return":"nonempty string"},"differential.getcommitpaths":{"description":"Query which paths should be included when committing a Differential revision.","params":{"revision_id":"required int"},"return":"nonempty list\u003cstring\u003e"},"differential.getrawdiff":{"description":"Retrieve a raw diff","params":{"diffID":"required diffID"},"return":"nonempty string"},"differential.parsecommitmessage":{"description":"Parse commit messages for Differential fields.","params":{"corpus":"required string","partial":"optional bool"},"return":"nonempty dict"},"differential.query":{"description":"Query Differential revisions which match certain criteria.","params":{"authors":"optional list\u003cphid\u003e","ccs":"optional list\u003cphid\u003e","reviewers":"optional list\u003cphid\u003e","paths":"optional list\u003cpair\u003ccallsign, path\u003e\u003e","commitHashes":"optional list\u003cpair\u003cstring-constant\u003c\"gtcm\", \"gttr\", \"hgcm\"\u003e, string\u003e\u003e","status":"optional string-constant\u003c\"status-any\", \"status-open\", \"status-accepted\", \"status-closed\"\u003e","order":"optional string-constant\u003c\"order-modified\", \"order-created\"\u003e","limit":"optional uint","offset":"optional uint","ids":"optional list\u003cuint\u003e","phids":"optional list\u003cphid\u003e","subscribers":"optional list\u003cphid\u003e","responsibleUsers":"optional list\u003cphid\u003e","branches":"optional list\u003cstring\u003e"},"return":"list\u003cdict\u003e"},"differential.querydiffs":{"description":"Query differential diffs which match certain criteria.","params":{"ids":"optional list\u003cuint\u003e","revisionIDs":"optional list\u003cuint\u003e"},"return":"list\u003cdict\u003e"},"differential.setdiffproperty":{"description":"Attach properties to Differential diffs.","params":{"diff_id":"required diff_id","name":"required string","data":"required string"},"return":"void"},"differential.updaterevision":{"description":"Update a Differential revision.","params":{"id":"required revisionid","diffid":"required diffid","fields":"required dict","message":"required string"},"return":"nonempty dict"},"differential.revision.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"differential.find":{"description":"Query Differential revisions which match certain criteria.","params":{"query":"required string-constant\u003c\"open\", \"committable\", \"revision-ids\", \"phids\"\u003e","guids":"required nonempty list\u003cguids\u003e"},"return":"nonempty list\u003cdict\u003e"},"differential.getalldiffs":{"description":"Load all diffs for given revisions from Differential.","params":{"revision_ids":"required list\u003cint\u003e"},"return":"dict"},"differential.getdiff":{"description":"Load the content of a diff from Differential by revision ID or diff ID.","params":{"revision_id":"optional id","diff_id":"optional id"},"return":"nonempty dict"},"differential.getrevision":{"description":"Load the content of a revision from Differential.","params":{"revision_id":"required id"},"return":"nonempty dict"},"differential.getrevisioncomments":{"description":"Retrieve Differential Revision Comments.","params":{"ids":"required list\u003cint\u003e","inlines":"optional bool (deprecated)"},"return":"nonempty list\u003cdict\u003cstring, wild\u003e\u003e"},"diffusion.commit.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https://secure.phabricator.com/diviner/find/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"after":"optional string","attachments":"optional map","before":"optional string","constraints":"optional map","limit":"optional int (default = 100)","order":"optional order","queryKey":"optional string"},"return":"list"},"diffusion.findsymbols":{"description":"Retrieve Diffusion symbol information.","params":{"name":"optional string","namePrefix":"optional string","context":"optional string","language":"optional string","type":"optional string","repositoryPHID":"optional string"},"return":"nonempty list\u003cdict\u003e"},"diffusion.getrecentcommitsbypath":{"description":"Get commit identifiers for recent commits affecting a given path.","params":{"callsign":"required string","path":"required string","branch":"optional string","limit":"optional int"},"return":"nonempty list\u003cstring\u003e"},"diffusion.querycommits":{"description":"Retrieve information about commits.","params":{"ids":"optional list\u003cint\u003e","phids":"optional list\u003cphid\u003e","names":"optional list\u003cstring\u003e","repositoryPHID":"optional phid","needMessages":"optional bool","bypassCache":"optional bool","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, dict\u003e"},"diffusion.blame":{"description":"Get blame information for a list of paths.","params":{"paths":"required list\u003cstring\u003e","commit":"required string","timeout":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"map\u003cstring, wild\u003e"},"diffusion.branchquery":{"description":"Determine what branches exist for a repository.","params":{"closed":"optional bool","limit":"optional int","offset":"optional int","contains":"optional string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"list\u003cdict\u003e"},"diffusion.browsequery":{"description":"File(s) information for a repository at an (optional) path and (optional) commit.","params":{"path":"optional string","commit":"optional string","needValidityOnly":"optional bool","limit":"optional int","offset":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.commitparentsquery":{"description":"Get the commit identifiers for a commit's parent or parents.","params":{"commit":"required string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"list\u003cstring\u003e"},"diffusion.diffquery":{"description":"Get diff information from a repository for a specific path at an (optional) commit.","params":{"path":"required string","commit":"optional string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.existsquery":{"description":"Determine if code exists in a version control system.","params":{"commit":"required string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"bool"},"diffusion.filecontentquery":{"description":"Retrieve file content from a repository.","params":{"path":"required string","commit":"required string","timeout":"optional int","byteLimit":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.getlintmessages":{"description":"Get lint messages for existing code.","params":{"repositoryPHID":"required phid","branch":"required string","commit":"optional string","files":"required list\u003cstring\u003e"},"return":"list\u003cdict\u003e"},"diffusion.historyquery":{"description":"Returns history information for a repository at a specific commit and path.","params":{"commit":"required string","path":"required string","offset":"required int","limit":"required int","needDirectChanges":"optional bool","needChildChanges":"optional bool","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.internal.gitrawdiffquery":{"description":"Internal method for getting raw diff information.","params":{"commit":"required string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"string"},"diffusion.lastmodifiedquery":{"description":"Get the commits at which paths were last modified.","params":{"paths":"required map\u003cstring, string\u003e","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"map\u003cstring, string\u003e"},"diffusion.looksoon":{"description":"Advises Phabricator to look for new commits in a repository as soon as possible. This advice is most useful if you have just pushed new commits to that repository.","params":{"callsigns":"optional list\u003cstring\u003e (deprecated)","repositories":"optional list\u003cstring\u003e","urgency":"optional string"},"return":"void"},"diffusion.mergedcommitsquery":{"description":"Merged commit information for a specific commit in a repository.","params":{"commit":"required string","limit":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.querypaths":{"description":"Filename search on a repository.","params":{"path":"required string","commit":"required string","pattern":"optional string","limit":"optional int","offset":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"list\u003cstring\u003e"},"diffusion.rawdiffquery":{"description":"Get raw diff information from a repository for a specific commit at an (optional) path.","params":{"commit":"required string","path":"optional string","timeout":"optional int","byteLimit":"optional int","linesOfContext":"optional int","againstCommit":"optional string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"string"},"diffusion.refsquery":{"description":"Query a git repository for ref information at a specific commit.","params":{"commit":"required string","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.repository.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"diffusion.repository.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"diffusion.resolverefs":{"description":"Resolve references into stable, canonical identifiers.","params":{"refs":"required list\u003cstring\u003e","types":"optional list\u003cstring\u003e","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"dict\u003cstring, list\u003cdict\u003cstring, wild\u003e\u003e\u003e"},"diffusion.searchquery":{"description":"Search (grep) a repository at a specific path and commit.","params":{"path":"required string","commit":"optional string","grep":"required string","limit":"optional int","offset":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.tagsquery":{"description":"Retrieve information about tags in a repository.","params":{"names":"optional list\u003cstring\u003e","commit":"optional string","needMessages":"optional bool","offset":"optional int","limit":"optional int","callsign":"optional string (deprecated)","repository":"optional string","branch":"optional string"},"return":"array"},"diffusion.updatecoverage":{"description":"Publish coverage information for a repository.","params":{"repositoryPHID":"required phid","branch":"required string","commit":"required string","coverage":"required map\u003cstring, string\u003e","mode":"optional string-constant\u003c\"overwrite\", \"update\"\u003e"},"return":"void"},"diffusion.uri.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"diffusion.createcomment":{"description":"Add a comment to a Diffusion commit. By specifying an action of \"concern\", \"accept\", \"resign\", or \"close\", auditing actions can be triggered. Defaults to \"comment\".","params":{"phid":"required string","action":"optional string","message":"required string","silent":"optional bool"},"return":"bool"},"feed.publish":{"description":"Publish a story to the feed.","params":{"type":"required string","data":"required dict","time":"optional int"},"return":"nonempty phid"},"feed.query":{"description":"Query the feed for stories","params":{"filterPHIDs":"optional list \u003cphid\u003e","limit":"optional int (default 100)","after":"optional int","before":"optional int","view":"optional string (data, html, html-summary, text)"},"return":"nonempty dict"},"file.allocate":{"description":"Prepare to upload a file.","params":{"name":"string","contentLength":"int","contentHash":"optional string","viewPolicy":"optional string","deleteAfterEpoch":"optional int"},"return":"map\u003cstring, wild\u003e"},"file.download":{"description":"Download a file from the server.","params":{"phid":"required phid"},"return":"nonempty base64-bytes"},"file.info":{"description":"Get information about a file.","params":{"phid":"optional phid","id":"optional id"},"return":"nonempty dict"},"file.querychunks":{"description":"Get information about file chunks.","params":{"filePHID":"phid"},"return":"list\u003cwild\u003e"},"file.upload":{"description":"Upload a file to the server.","params":{"data_base64":"required nonempty base64-bytes","name":"optional string","viewPolicy":"optional valid policy string or \u003cphid\u003e","canCDN":"optional bool"},"return":"nonempty guid"},"file.uploadchunk":{"description":"Upload a chunk of file data to the server.","params":{"filePHID":"phid","byteStart":"int","data":"string","dataEncoding":"string"},"return":"void"},"file.uploadhash":{"description":"Upload a file to the server using content hash.","params":{"hash":"required nonempty string","name":"required nonempty string"},"return":"phid or null"},"flag.delete":{"description":"Clear a flag.","params":{"id":"optional id","objectPHID":"optional phid"},"return":"dict | null"},"flag.edit":{"description":"Create or modify a flag.","params":{"objectPHID":"required phid","color":"optional int","note":"optional string"},"return":"dict"},"flag.query":{"description":"Query flag markers.","params":{"ownerPHIDs":"optional list\u003cphid\u003e","types":"optional list\u003ctype\u003e","objectPHIDs":"optional list\u003cphid\u003e","offset":"optional int","limit":"optional int (default = 100)"},"return":"list\u003cdict\u003e"},"harbormaster.createartifact":{"description":"Use this method to attach artifacts to build targets while running builds. Artifacts can be used to carry data through a complex build workflow, provide extra information to users, or store build results.\n\nWhen creating an artifact, you will choose an `artifactType` from this table. These types of artifacts are supported:\n| Artifact Type | Name | Summary |\n|-------------|--------------|--------------|\n| `host` | **Drydock Host** | References a host lease from Drydock. |\n| `working-copy` | **Drydock Working Copy** | References a working copy lease from Drydock. |\n| `file` | **File** | Stores a reference to file data which has been uploaded to Phabricator. |\n| `uri` | **URI** | Stores a URI. |\n\nEach artifact also needs an `artifactKey`, which names the artifact. Finally, you will provide some `artifactData` to fill in the content of the artifact. The data you provide depends on what type of artifact you are creating.\nDrydock Host\n--------------------------\n\nReferences a host lease from Drydock.\n\nCreate an artifact of this type by passing `host` as the `artifactType`. When creating an artifact of this type, provide these parameters as a dictionary to `artifactData`:\n| Key | Type | Description |\n|-------------|--------------|--------------|\n| `drydockLeasePHID` | \/\/string\/\/ | Drydock working copy lease to create an artifact from. |\nFor example:\n```lang=json\n{\n \"drydockLeasePHID\": \"PHID-DRYL-abcdefghijklmnopqrst\"\n}\n\n```\nDrydock Working Copy\n--------------------------\n\nReferences a working copy lease from Drydock.\n\nCreate an artifact of this type by passing `working-copy` as the `artifactType`. When creating an artifact of this type, provide these parameters as a dictionary to `artifactData`:\n| Key | Type | Description |\n|-------------|--------------|--------------|\n| `drydockLeasePHID` | \/\/string\/\/ | Drydock working copy lease to create an artifact from. |\nFor example:\n```lang=json\n{\n \"drydockLeasePHID\": \"PHID-DRYL-abcdefghijklmnopqrst\"\n}\n\n```\nFile\n--------------------------\n\nStores a reference to file data which has been uploaded to Phabricator.\n\nCreate an artifact of this type by passing `file` as the `artifactType`. When creating an artifact of this type, provide these parameters as a dictionary to `artifactData`:\n| Key | Type | Description |\n|-------------|--------------|--------------|\n| `filePHID` | \/\/string\/\/ | File to create an artifact from. |\nFor example:\n```lang=json\n{\n \"filePHID\": \"PHID-FILE-abcdefghijklmnopqrst\"\n}\n\n```\nURI\n--------------------------\n\nStores a URI.\n\nWith `ui.external`, you can use this artifact type to add links to build results in an external build system.\n\nCreate an artifact of this type by passing `uri` as the `artifactType`. When creating an artifact of this type, provide these parameters as a dictionary to `artifactData`:\n| Key | Type | Description |\n|-------------|--------------|--------------|\n| `uri` | \/\/string\/\/ | The URI to store. |\n| `name` | \/\/optional string\/\/ | Optional label for this URI. |\n| `ui.external` | \/\/optional bool\/\/ | If true, display this URI in the UI as an link to additional build details in an external build system. |\nFor example:\n```lang=json\n{\n \"uri\": \"https:\/\/buildserver.mycompany.com\/build\/123\/\",\n \"name\": \"View External Build Results\",\n \"ui.external\": true\n}\n\n```","params":{"buildTargetPHID":"phid","artifactKey":"string","artifactType":"string","artifactData":"map\u003cstring, wild\u003e"},"return":"wild"},"harbormaster.queryautotargets":{"description":"Load or create build autotargets.","params":{"objectPHID":"phid","targetKeys":"list\u003cstring\u003e"},"return":"map\u003cstring, phid\u003e"},"harbormaster.querybuildables":{"description":"Query Harbormaster buildables.","params":{"ids":"optional list\u003cid\u003e","phids":"optional list\u003cphid\u003e","buildablePHIDs":"optional list\u003cphid\u003e","containerPHIDs":"optional list\u003cphid\u003e","manualBuildables":"optional bool","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"wild"},"harbormaster.querybuilds":{"description":"Query Harbormaster builds.","params":{"ids":"optional list\u003cid\u003e","phids":"optional list\u003cphid\u003e","buildStatuses":"optional list\u003cstring\u003e","buildablePHIDs":"optional list\u003cphid\u003e","buildPlanPHIDs":"optional list\u003cphid\u003e","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"wild"},"harbormaster.sendmessage":{"description":"Send a message about the status of a build target to Harbormaster, notifying the application of build results in an external system.\n\nSending Messages\n================\nIf you run external builds, you can use this method to publish build results back into Harbormaster after the external system finishes work or as it makes progress.\n\nThe simplest way to use this method is to call it once after the build finishes with a `pass` or `fail` message. This will record the build result, and continue the next step in the build if the build was waiting for a result.\n\nWhen you send a status message about a build target, you can optionally include detailed `lint` or `unit` results alongside the message. See below for details.\n\nIf you want to report intermediate results but a build hasn't completed yet, you can use the `work` message. This message doesn't have any direct effects, but allows you to send additional data to update the progress of the build target. The target will continue waiting for a completion message, but the UI will update to show the progress which has been made.\n\nMessage Types\n=============\nWhen you send Harbormaster a message, you must include a `type`, which describes the overall state of the build. For example, use `pass` to tell Harbomaster that a build completed successfully.\n\nSupported message types are:\n\n| Type | Description |\n|--------------|--------------|\n| `pass` | Report that the target is complete, and the target has passed. |\n| `fail` | Report that the target is complete, and the target has failed. |\n| `work` | Report that work on the target is ongoing. This message can be used to report partial results during a build. |\n\nUnit Results\n============\nYou can report test results alongside a message. The simplest way to do this is to report all the results alongside a `pass` or `fail` message, but you can also send a `work` message to report intermediate results.\n\nTo provide unit test results, pass a list of results in the `unit` parameter. Each result shoud be a dictionary with these keys:\n\n| Key | Type | Description |\n|-------------|--------------|--------------|\n| `name` | \/\/string\/\/ | Short test name, like \"ExampleTest\". |\n| `result` | \/\/string\/\/ | Result of the test. |\n| `namespace` | \/\/optional string\/\/ | Optional namespace for this test. This is organizational and is often a class or module name, like \"ExampleTestCase\". |\n| `engine` | \/\/optional string\/\/ | Test engine running the test, like \"JavascriptTestEngine\". This primarily prevents collisions between tests with the same name in different test suites (for example, a Javascript test and a Python test). |\n| `duration` | \/\/optional float or int\/\/ | Runtime duration of the test, in seconds. |\n| `path` | \/\/optional string\/\/ | Path to the file where the test is declared, relative to the project root. |\n| `coverage` | \/\/optional map\u003cstring, wild\u003e\/\/ | Coverage information for this test. |\n| `details` | \/\/optional string\/\/ | Additional human-readable information about the failure. |\n\nThe `result` parameter recognizes these test results:\n\n| Key | Name | Description |\n|-------------|--------------|--------------|\n| `pass` | **Pass** | The test passed. |\n| `fail` | **Fail** | The test failed. |\n| `skip` | **Skip** | The test was not executed. |\n| `broken` | **Broken** | The test failed in an abnormal or severe way. For example, the harness crashed instead of reporting a failure. |\n| `unsound` | **Unsound** | The test failed, but this change is probably not what broke it. For example, it might have already been failing. |\n\nThis is a simple, valid value for the `unit` parameter. It reports one passing test and one failing test:\n\n\n\n```lang=json\n[\n {\n \"name\": \"PassingTest\",\n \"result\": \"pass\"\n },\n {\n \"name\": \"FailingTest\",\n \"result\": \"fail\"\n }\n]\n```\n\nLint Results\n============\nLike unit test results, you can report lint results alongside a message. The `lint` parameter should contain results as a list of dictionaries with these keys:\n\n| Key | Type | Description |\n|-------------|--------------|--------------|\n| `name` | \/\/string\/\/ | Short message name, like \"Syntax Error\". |\n| `code` | \/\/string\/\/ | Lint message code identifying the type of message, like \"ERR123\". |\n| `severity` | \/\/string\/\/ | Severity of the message. |\n| `path` | \/\/string\/\/ | Path to the file containing the lint message, from the project root. |\n| `line` | \/\/optional int\/\/ | Line number in the file where the text which triggered the message first appears. The first line of the file is line 1, not line 0. |\n| `char` | \/\/optional int\/\/ | Byte position on the line where the text which triggered the message starts. The first byte on the line is byte 1, not byte 0. This position is byte-based (not character-based) because not all lintable files have a valid character encoding. |\n| `description` | \/\/optional string\/\/ | Long explanation of the lint message. |\n\nThe `severity` parameter recognizes these severity levels:\n\n| Key | Name |\n|-------------|--------------|\n| `advice` | **Advice** |\n| `autofix` | **Auto-Fix** |\n| `warning` | **Warning** |\n| `error` | **Error** |\n| `disabled` | **Disabled** |\n\nThis is a simple, valid value for the `lint` parameter. It reports one error and one warning:\n\n```lang=json\n[\n {\n \"name\": \"Syntax Error\",\n \"code\": \"EXAMPLE1\",\n \"severity\": \"error\",\n \"path\": \"path\/to\/example.c\",\n \"line\": 17,\n \"char\": 3\n },\n {\n \"name\": \"Not A Haiku\",\n \"code\": \"EXAMPLE2\",\n \"severity\": \"error\",\n \"path\": \"path\/to\/source.cpp\",\n \"line\": 23,\n \"char\": 1,\n \"description\": \"This function definition is not a haiku.\"\n }\n]\n```\n\n","params":{"buildTargetPHID":"required phid","type":"required string-constant\u003c\"pass\", \"fail\", \"work\"\u003e","unit":"optional list\u003cwild\u003e","lint":"optional list\u003cwild\u003e"},"return":"void"},"macro.query":{"description":"Retrieve image macro information.","params":{"authorPHIDs":"optional list\u003cphid\u003e","phids":"optional list\u003cphid\u003e","ids":"optional list\u003cid\u003e","names":"optional list\u003cstring\u003e","nameLike":"optional string"},"return":"list\u003cdict\u003e"},"macro.creatememe":{"description":"Generate a meme.","params":{"macroName":"string","upperText":"optional string","lowerText":"optional string"},"return":"string"},"maniphest.createtask":{"description":"Create a new Maniphest task.","params":{"title":"required string","description":"optional string","ownerPHID":"optional phid","viewPolicy":"optional phid or policy string","editPolicy":"optional phid or policy string","ccPHIDs":"optional list\u003cphid\u003e","priority":"optional int","projectPHIDs":"optional list\u003cphid\u003e","auxiliary":"optional dict"},"return":"nonempty dict"},"maniphest.gettasktransactions":{"description":"Retrieve Maniphest task transactions.","params":{"ids":"required list\u003cint\u003e"},"return":"nonempty list\u003cdict\u003cstring, wild\u003e\u003e"},"maniphest.info":{"description":"Retrieve information about a Maniphest task, given its ID.","params":{"task_id":"required id"},"return":"nonempty dict"},"maniphest.query":{"description":"Execute complex searches for Maniphest tasks.","params":{"ids":"optional list\u003cuint\u003e","phids":"optional list\u003cphid\u003e","ownerPHIDs":"optional list\u003cphid\u003e","authorPHIDs":"optional list\u003cphid\u003e","projectPHIDs":"optional list\u003cphid\u003e","ccPHIDs":"optional list\u003cphid\u003e","fullText":"optional string","status":"optional string-constant\u003c\"status-any\", \"status-open\", \"status-closed\", \"status-resolved\", \"status-wontfix\", \"status-invalid\", \"status-spite\", \"status-duplicate\"\u003e","order":"optional string-constant\u003c\"order-priority\", \"order-created\", \"order-modified\"\u003e","limit":"optional int","offset":"optional int"},"return":"list"},"maniphest.querystatuses":{"description":"Retrieve information about possible Maniphest task status values.","params":[],"return":"nonempty dict\u003cstring, wild\u003e"},"maniphest.update":{"description":"Update an existing Maniphest task.","params":{"id":"optional int","phid":"optional int","title":"optional string","description":"optional string","ownerPHID":"optional phid","viewPolicy":"optional phid or policy string","editPolicy":"optional phid or policy string","ccPHIDs":"optional list\u003cphid\u003e","priority":"optional int","projectPHIDs":"optional list\u003cphid\u003e","auxiliary":"optional dict","status":"optional string","comments":"optional string"},"return":"nonempty dict"},"maniphest.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"maniphest.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"owners.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"owners.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"owners.query":{"description":"Query for Owners packages. Obsoleted by \"owners.search\".","params":{"userOwner":"optional string","projectOwner":"optional string","userAffiliated":"optional string","repositoryCallsign":"optional string","path":"optional string"},"return":"dict\u003cphid -\u003e dict of package info\u003e"},"passphrase.query":{"description":"Query credentials.","params":{"ids":"optional list\u003cint\u003e","phids":"optional list\u003cphid\u003e","needSecrets":"optional bool","needPublicKeys":"optional bool","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"list\u003cdict\u003e"},"paste.create":{"description":"Create a new paste.","params":{"content":"required string","title":"optional string","language":"optional string"},"return":"nonempty dict"},"paste.query":{"description":"Query Pastes.","params":{"ids":"optional list\u003cint\u003e","phids":"optional list\u003cphid\u003e","authorPHIDs":"optional list\u003cphid\u003e","after":"optional int","limit":"optional int, default = 100"},"return":"list\u003cdict\u003e"},"paste.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"paste.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"paste.info":{"description":"Retrieve an array of information about a paste.","params":{"paste_id":"required id"},"return":"nonempty dict"},"phame.blog.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"phame.blog.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"phame.post.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"phame.post.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"phid.lookup":{"description":"Look up objects by name.","params":{"names":"required list\u003cstring\u003e"},"return":"nonempty dict\u003cstring, wild\u003e"},"phid.query":{"description":"Retrieve information about arbitrary PHIDs.","params":{"phids":"required list\u003cphid\u003e"},"return":"nonempty dict\u003cstring, wild\u003e"},"phid.info":{"description":"Retrieve information about an arbitrary PHID.","params":{"phid":"required phid"},"return":"nonempty dict\u003cstring, wild\u003e"},"phragment.getpatch":{"description":"Retrieve the patches to apply for a given set of files.","params":{"path":"required string","state":"required dict\u003cstring, string\u003e"},"return":"nonempty dict"},"phragment.queryfragments":{"description":"Query fragments based on their paths.","params":{"paths":"required list\u003cstring\u003e"},"return":"nonempty dict"},"phriction.create":{"description":"Create a Phriction document.","params":{"slug":"required string","title":"required string","content":"required string","description":"optional string"},"return":"nonempty dict"},"phriction.edit":{"description":"Update a Phriction document.","params":{"slug":"required string","title":"optional string","content":"optional string","description":"optional string"},"return":"nonempty dict"},"phriction.history":{"description":"Retrieve history about a Phriction document.","params":{"slug":"required string"},"return":"nonempty list"},"phriction.info":{"description":"Retrieve information about a Phriction document.","params":{"slug":"required string"},"return":"nonempty dict"},"project.create":{"description":"Create a project.","params":{"name":"required string","members":"optional list\u003cphid\u003e","icon":"optional string","color":"optional string","tags":"optional list\u003cstring\u003e"},"return":"dict"},"project.query":{"description":"Execute searches for Projects.","params":{"ids":"optional list\u003cint\u003e","names":"optional list\u003cstring\u003e","phids":"optional list\u003cphid\u003e","slugs":"optional list\u003cstring\u003e","icons":"optional list\u003cstring\u003e","colors":"optional list\u003cstring\u003e","status":"optional string-constant\u003c\"status-any\", \"status-open\", \"status-closed\", \"status-active\", \"status-archived\"\u003e","members":"optional list\u003cphid\u003e","limit":"optional int","offset":"optional int"},"return":"list"},"project.edit":{"description":"This is a standard **ApplicationEditor** method which allows you to create and modify objects by applying transactions. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Edit+Endpoints&type=article&jump=1 | Conduit API: Using Edit Endpoints ]]**.","params":{"transactions":"list\u003cmap\u003cstring, wild\u003e\u003e","objectIdentifier":"optional id|phid|string"},"return":"map\u003cstring, wild\u003e"},"project.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"releeph.getbranches":{"description":"Return information about all active Releeph branches.","params":[],"return":"nonempty list\u003cdict\u003cstring, wild\u003e\u003e"},"releeph.querybranches":{"description":"Query information about Releeph branches.","params":{"ids":"optional list\u003cid\u003e","phids":"optional list\u003cphid\u003e","productPHIDs":"optional list\u003cphid\u003e","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"query-results"},"releeph.queryproducts":{"description":"Query information about Releeph products.","params":{"ids":"optional list\u003cid\u003e","phids":"optional list\u003cphid\u003e","repositoryPHIDs":"optional list\u003cphid\u003e","isActive":"optional bool","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"query-results"},"releeph.queryrequests":{"description":"Return information about all Releeph requests linked to the given ids.","params":{"revisionPHIDs":"optional list\u003cphid\u003e","requestedCommitPHIDs":"optional list\u003cphid\u003e"},"return":"dict\u003cstring, wild\u003e"},"releeph.request":{"description":"Request a commit or diff to be picked to a branch.","params":{"branchPHID":"required string","things":"required list\u003cstring\u003e","fields":"dict\u003cstring, string\u003e"},"return":"dict\u003cstring, wild\u003e"},"releephwork.canpush":{"description":"Return whether the conduit user is allowed to push.","params":{"projectPHID":"required string"},"return":"bool"},"releephwork.getauthorinfo":{"description":"Return a string to use as the VCS author.","params":{"userPHID":"required string","vcsType":"required string"},"return":"nonempty string"},"releephwork.getbranch":{"description":"Return information to help checkout \/ cut a Releeph branch.","params":{"branchPHID":"required string"},"return":"dict\u003cstring, wild\u003e"},"releephwork.getbranchcommitmessage":{"description":"Get a commit message for committing a Releeph branch.","params":{"branchPHID":"required string"},"return":"nonempty string"},"releephwork.getcommitmessage":{"description":"Get commit message components for building a ReleephRequest commit message.","params":{"requestPHID":"required string","action":"required string-constant\u003c\"pick\", \"revert\"\u003e"},"return":"dict\u003cstring, string\u003e"},"releephwork.nextrequest":{"description":"Return info required to cut a branch, and pick and revert ReleephRequests.","params":{"branchPHID":"required phid","seen":"required map\u003cstring, bool\u003e"},"return":""},"releephwork.record":{"description":"Record whether we committed a pick or revert to the upstream repository.","params":{"requestPHID":"required string","action":"required string-constant\u003c\"pick\", \"revert\"\u003e","commitIdentifier":"required string"},"return":"void"},"releephwork.recordpickstatus":{"description":"Record whether a pick or revert was successful or not.","params":{"requestPHID":"required string","action":"required string-constant\u003c\"pick\", \"revert\"\u003e","ok":"required bool","dryRun":"optional bool","details":"optional dict\u003cstring, wild\u003e"},"return":""},"remarkup.process":{"description":"Process text through remarkup in Phabricator context.","params":{"context":"required string-constant\u003c\"phriction\", \"maniphest\", \"differential\", \"phame\", \"feed\", \"diffusion\"\u003e","contents":"required list\u003cstring\u003e"},"return":"nonempty dict"},"repository.query":{"description":"Query repositories.","params":{"ids":"optional list\u003cint\u003e","phids":"optional list\u003cphid\u003e","callsigns":"optional list\u003cstring\u003e","vcsTypes":"optional list\u003cstring\u003e","remoteURIs":"optional list\u003cstring\u003e","uuids":"optional list\u003cstring\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"list\u003cdict\u003e"},"slowvote.info":{"description":"Retrieve an array of information about a poll.","params":{"poll_id":"required id"},"return":"nonempty dict"},"token.give":{"description":"Give or change a token.","params":{"tokenPHID":"phid|null","objectPHID":"phid"},"return":"void"},"token.given":{"description":"Query tokens given to objects.","params":{"authorPHIDs":"list\u003cphid\u003e","objectPHIDs":"list\u003cphid\u003e","tokenPHIDs":"list\u003cphid\u003e"},"return":"list\u003cdict\u003e"},"token.query":{"description":"Query tokens.","params":[],"return":"list\u003cdict\u003e"},"user.disable":{"description":"Permanently disable specified users (admin only).","params":{"phids":"required list\u003cphid\u003e"},"return":"void"},"user.enable":{"description":"Re-enable specified users (admin only).","params":{"phids":"required list\u003cphid\u003e"},"return":"void"},"user.query":{"description":"Query users.","params":{"usernames":"optional list\u003cstring\u003e","emails":"optional list\u003cstring\u003e","realnames":"optional list\u003cstring\u003e","phids":"optional list\u003cphid\u003e","ids":"optional list\u003cuint\u003e","offset":"optional int","limit":"optional int (default = 100)"},"return":"list\u003cdict\u003e"},"user.whoami":{"description":"Retrieve information about the logged-in user.","params":[],"return":"nonempty dict\u003cstring, wild\u003e"},"user.search":{"description":"This is a standard **ApplicationSearch** method which will let you list, query, or search for objects. For documentation on these endpoints, see **[[ https:\/\/secure.phabricator.com\/diviner\/find\/?name=Conduit+API%3A+Using+Search+Endpoints&type=article&jump=1 | Conduit API: Using Search Endpoints ]]**.","params":{"queryKey":"optional string","constraints":"optional map\u003cstring, wild\u003e","attachments":"optional map\u003cstring, bool\u003e","order":"optional order","before":"optional string","after":"optional string","limit":"optional int (default = 100)"},"return":"map\u003cstring, wild\u003e"},"user.find":{"description":"Lookup PHIDs by username. Obsoleted by \"user.query\".","params":{"aliases":"required list\u003cstring\u003e"},"return":"nonempty dict\u003cstring, phid\u003e"}} \ No newline at end of file diff --git a/contrib/buildbot/python_phabricator/phabricator/tests/__init__.py b/contrib/buildbot/python_phabricator/phabricator/tests/__init__.py deleted file mode 100644 diff --git a/contrib/buildbot/python_phabricator/phabricator/tests/resources/__init__.py b/contrib/buildbot/python_phabricator/phabricator/tests/resources/__init__.py deleted file mode 100644 diff --git a/contrib/buildbot/python_phabricator/phabricator/tests/resources/certificate.txt b/contrib/buildbot/python_phabricator/phabricator/tests/resources/certificate.txt deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/phabricator/tests/resources/certificate.txt +++ /dev/null @@ -1 +0,0 @@ -fdhcq3zsyijnm4h6gmh43zue5umsmng5t4dlwodvmiz4cnc6fl6fzrvjbfg2ftktrcddan7b3xtgmfge2afbrh4uwam6pfxpq5dbkhbl6mgaijdzpq5efw2ynlnjhoeqyh6dakl4yg346gbhabzkcxreu7hcjhw6vo6wwa7ky2sjdk742khlgsakwtme6sr2dfkhlxxkcqw3jngyrq5zj7m6m7hnscuzlzsviawnvg47pe7l4hxiexpbb5k456r diff --git a/contrib/buildbot/python_phabricator/phabricator/tests/resources/responses.json b/contrib/buildbot/python_phabricator/phabricator/tests/resources/responses.json deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/phabricator/tests/resources/responses.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "conduit.connect": "{\"result\":{\"connectionID\":1759,\"sessionKey\":\"lwvyv7f6hlzb2vawac6reix7ejvjty72svnir6zy\",\"userPHID\":\"PHID-USER-6ij4rnamb2gsfpdkgmny\"},\"error_code\":null,\"error_info\":null}", - "user.whoami": "{\"result\":{\"phid\":\"PHID-USER-6ij4rnamz2gxfpbkamny\",\"userName\":\"testaccount\",\"realName\":\"Test Account\"},\"error_code\":null,\"error_info\":null}", - "maniphest.find": "{\"result\":{\"PHID-TASK-4cgpskv6zzys6rp5rvrc\":{\"id\":\"722\",\"phid\":\"PHID-TASK-4cgpskv6zzys6rp5rvrc\",\"authorPHID\":\"PHID-USER-5022a9389121884ab9db\",\"ownerPHID\":\"PHID-USER-5022a9389121884ab9db\",\"ccPHIDs\":[\"PHID-USER-5022a9389121884ab9db\",\"PHID-USER-ba8aeea1b3fe2853d6bb\"],\"status\":\"3\",\"priority\":\"Needs Triage\",\"title\":\"Relations should be two-way\",\"description\":\"When adding a differential revision you can specify Maniphest Tickets to add the relation. However, this doesnt add the relation from the ticket -> the differently.(This was added via the commit message)\",\"projectPHIDs\":[\"PHID-PROJ-358dbc2e601f7e619232\",\"PHID-PROJ-f58a9ac58c333f106a69\"],\"uri\":\"https://secure.phabricator.com/T722\",\"auxiliary\":[],\"objectName\":\"T722\",\"dateCreated\":\"1325553508\",\"dateModified\":\"1325618490\"}},\"error_code\":null,\"error_info\":null}" -} diff --git a/contrib/buildbot/python_phabricator/phabricator/tests/test_phabricator.py b/contrib/buildbot/python_phabricator/phabricator/tests/test_phabricator.py deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/phabricator/tests/test_phabricator.py +++ /dev/null @@ -1,174 +0,0 @@ -try: - import unittest2 as unittest -except ImportError: - import unittest - -import requests -import responses - -from pkg_resources import resource_string -import json - -import phabricator -phabricator.ARCRC = {} # overwrite any arcrc that might be read - - -RESPONSES = json.loads( - resource_string( - 'phabricator.tests.resources', - 'responses.json' - ).decode('utf8') -) -CERTIFICATE = resource_string( - 'phabricator.tests.resources', - 'certificate.txt' -).decode('utf8').strip() - - -# Protect against local user's .arcrc interference. -phabricator.ARCRC = {} - - -class PhabricatorTest(unittest.TestCase): - def setUp(self): - self.api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - self.api.certificate = CERTIFICATE - - def test_generate_hash(self): - token = '12345678' - hashed = self.api.generate_hash(token) - self.assertEqual(hashed, 'f8d3bea4e58a2b2967d93d5b307bfa7c693b2e7f') - - @responses.activate - def test_connect(self): - responses.add('POST', 'http://localhost/api/conduit.connect', - body=RESPONSES['conduit.connect'], status=200) - - api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - - api.connect() - keys = api._conduit.keys() - self.assertIn('sessionKey', keys) - self.assertIn('connectionID', keys) - assert len(responses.calls) == 1 - - @responses.activate - def test_user_whoami(self): - responses.add('POST', 'http://localhost/api/user.whoami', - body=RESPONSES['user.whoami'], status=200) - - api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - api._conduit = True - - self.assertEqual(api.user.whoami()['userName'], 'testaccount') - - def test_classic_resources(self): - api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - - self.assertEqual(api.user.whoami.method, 'user') - self.assertEqual(api.user.whoami.endpoint, 'whoami') - - def test_nested_resources(self): - api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - - self.assertEqual(api.diffusion.repository.edit.method, 'diffusion') - self.assertEqual( - api.diffusion.repository.edit.endpoint, 'repository.edit') - - @responses.activate - def test_bad_status(self): - responses.add( - 'POST', 'http://localhost/api/conduit.connect', status=400) - - api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - - with self.assertRaises(requests.exceptions.HTTPError): - api.user.whoami() - assert len(responses.calls) == 1 - - @responses.activate - def test_maniphest_find(self): - responses.add('POST', 'http://localhost/api/maniphest.find', - body=RESPONSES['maniphest.find'], status=200) - - api = phabricator.Phabricator( - username='test', - certificate='test', - host='http://localhost/api/' - ) - api._conduit = True - - result = api.maniphest.find( - ownerphids=['PHID-USER-5022a9389121884ab9db'] - ) - self.assertEqual(len(result), 1) - - # Test iteration - self.assertIsInstance([x for x in result], list) - - # Test getattr - self.assertEqual( - result['PHID-TASK-4cgpskv6zzys6rp5rvrc']['status'], - '3' - ) - - def test_validation(self): - self.api._conduit = True - - self.assertRaises(ValueError, self.api.differential.find) - with self.assertRaises(ValueError): - self.api.differential.find(query=1) - with self.assertRaises(ValueError): - self.api.differential.find(query='1') - with self.assertRaises(ValueError): - self.api.differential.find(query='1', guids='1') - - def test_map_param_type(self): - uint = 'uint' - self.assertEqual(phabricator.map_param_type(uint), int) - - list_bool = 'list' - self.assertEqual(phabricator.map_param_type(list_bool), [bool]) - - list_pair = 'list>' - self.assertEqual(phabricator.map_param_type(list_pair), [tuple]) - - complex_list_pair = 'list, string>>' - self.assertEqual(phabricator.map_param_type( - complex_list_pair), [tuple]) - - - def test_endpoint_shadowing(self): - shadowed_endpoints = [e for e in self.api.interface.keys() if e in self.api.__dict__] - self.assertEqual( - shadowed_endpoints, - [], - "The following endpoints are shadowed: {}".format(shadowed_endpoints) - ) - -if __name__ == '__main__': - unittest.main() diff --git a/contrib/buildbot/python_phabricator/setup.cfg b/contrib/buildbot/python_phabricator/setup.cfg deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -universal=1 diff --git a/contrib/buildbot/python_phabricator/setup.py b/contrib/buildbot/python_phabricator/setup.py deleted file mode 100644 --- a/contrib/buildbot/python_phabricator/setup.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python - -import sys - -from setuptools import setup, find_packages - -tests_requires = ['responses>=0.12'] - -if sys.version_info[:2] < (2, 7): - tests_requires.append('unittest2') - -if sys.version_info[:2] <= (3, 3): - tests_requires.append('mock') - -setup( - name='phabricator', - version='0.7.0', - author='Disqus', - author_email='opensource@disqus.com', - url='http://github.com/disqus/python-phabricator', - description='Phabricator API Bindings', - packages=find_packages(), - zip_safe=False, - install_requires=['requests>=2.22'], - test_suite='phabricator.tests.test_phabricator', - extras_require={ - 'tests': tests_requires, - }, - include_package_data=True, - classifiers=[ - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'Operating System :: OS Independent', - 'Topic :: Software Development', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - ], -) diff --git a/contrib/buildbot/requirements.txt b/contrib/buildbot/requirements.txt --- a/contrib/buildbot/requirements.txt +++ b/contrib/buildbot/requirements.txt @@ -1,6 +1,7 @@ deepmerge mock flask +phabricator>=0.8.0 pyyaml requests responses