phabricator

Phabricator module.

wmflib.phabricator.create_phabricator(bot_config_file: str, *, section: str = 'phabricator_bot', allow_empty_identifiers: bool = False, dry_run: bool = True) Phabricator[source]

Initialize the Phabricator client from the bot config file.

Examples

>>> from wmflib.phabricator import create_phabricator, Phabricator
>>> phab_client = create_phabricator("/path/to/config.ini", dry_run=False)
>>> Phabricator.validate_task_id("T12345")
'T12345'
>>> if phab_client.task_accessible("T12345"):
...     phab_client.task_comment("T12345", "Message")
Parameters:
  • bot_config_file (str) –

    the path to the configuration file for the Phabricator bot, with the following structure:

    [section_name]
    host = https://phabricator.example.com/api/
    username = phab-bot
    token = api-12345
    

  • section (str, optional) – the name of the section of the configuration file where to find the required parameters.

  • allow_empty_identifiers – if set to True all the methods that require an ID (e.g. a task ID) will also accept an empty string as identifier and act as noop in that case.

  • dry_run (bool, optional) – whether this is a DRY-RUN.

Returns:

a Phabricator instance.

Return type:

wmflib.phabricator.Phabricator

Raises:

wmflib.phabricator.PhabricatorError – if unable to get all the required parameters from the bot configuration file, or to initialize the Phabricator client.

wmflib.phabricator.validate_task_id(task_id: str, *, allow_empty_identifiers: bool = False) str[source]

Phabricator task ID validator suitable to be used with argparse.ArgumentParser.add_argument().

Ensures that the task ID is properly formatted as T123456. Empty string are also accepted when setting allow_empty_identifiers=True, suitable to be used with argparse when the argument is optional with a default value of empty string.

Examples:

>>> validate_task_id("T1")
'T1'
>>> validate_task_id("T999999")
'T999999'
>>> validate_task_id("", allow_empty_identifiers=True)
''
>>> validate_task_id("T1234567")
Traceback (most recent call last):
  [...SNIP...]
ValueError: Invalid Phabricator task ID, expected to match pattern 'T\d{1,6}$', got 'T1234567'
Parameters:
  • task_id – the Phabricator task ID to validate.

  • allow_empty_identifiers – if set to True will consider an empty task as valid.

Raises:

ValueError – if the task_id is not properly formatted, so that argparse will properly format the error message. See also the argparse.ArgumentParser.add_argument() documentation.

Returns:

the task ID if valid.

exception wmflib.phabricator.PhabricatorError[source]

Bases: WmflibError

Custom exception class for errors of the Phabricator class.

__doc__ = 'Custom exception class for errors of the Phabricator class.'
__module__ = 'wmflib.phabricator'
class wmflib.phabricator.Phabricator(phabricator_client: Phabricator, *, dry_run: bool = True, allow_empty_identifiers: bool = False)[source]

Bases: object

Class to interact with a Phabricator website.

Initialize the Phabricator client from the bot config file.

Parameters:
  • phabricator_client (phabricator.Phabricator) – a Phabricator client instance.

  • dry_run (bool, optional) – whether this is a DRY-RUN.

  • allow_empty_identifiers – if set to True all the methods that require an ID (e.g. a task ID) will also accept an empty string as identifier and act as noop in that case.

__init__(phabricator_client: Phabricator, *, dry_run: bool = True, allow_empty_identifiers: bool = False) None[source]

Initialize the Phabricator client from the bot config file.

Parameters:
  • phabricator_client (phabricator.Phabricator) – a Phabricator client instance.

  • dry_run (bool, optional) – whether this is a DRY-RUN.

  • allow_empty_identifiers – if set to True all the methods that require an ID (e.g. a task ID) will also accept an empty string as identifier and act as noop in that case.

task_accessible(task_id: str, *, raises: bool = True) bool[source]

Check if a task exists and is accessible to the curirent API user.

Examples:

>>> phab_client.task_accessible("T1")
True
>>> phab_client.task_accessible("T1", raises=False)
True
>>> phab_client.task_accessible("T999999")
False
>>> phab_client.task_accessible("")  # with allow_empty_identifiers=True
DEBUG:wmflib.phabricator:No task specified and allow_empty_identifiers=True, nothing to check
False
>>> phab_client.task_accessible("", raises=False)  # with allow_empty_identifiers=True
DEBUG:wmflib.phabricator:No task specified and allow_empty_identifiers=True, nothing to check
False
>>> phab_client.task_accessible("", raises=False)  # with allow_empty_identifiers=False
ERROR:wmflib.phabricator:Unable to determine if the task '' is accessible (raises=False): Empty task ID
False
>>> phab_client.task_accessible("")  # with allow_empty_identifiers=False
Traceback (most recent call last):
  [...SNIP...]
wmflib.phabricator.PhabricatorError: Empty task ID
  [...SNIP...]
wmflib.phabricator.PhabricatorError: Unable to determine if the task '' is accessible
>>> phab_client.task_accessible("T1")
Traceback (most recent call last):
  [...SNIP...]
phabricator.APIError: ERR-INVALID-AUTH: API token "api-a" has the wrong length. [...SNIP...]
  [...SNIP...]
wmflib.phabricator.PhabricatorError: Unable to determine if the task 'T1' is accessible
>>> phab_client.task_accessible("T1", raises=False)
ERROR:wmflib.phabricator:Unable to determine if the task T1 is accessible (raises=False): ERR-[...SNIP...]
ERROR:wmflib.phabricator:Unable to determine if the task 'T1' is accessible (raises=False): ERR[...SNIP...]
False
Parameters:
  • task_id – the Phabricator task ID (e.g. T12345) to be updated. If empty string it will raise an exception unless allow_empty_identifiers is set to True. In this case it returns False and logs a message at debug level.

  • raises – if set to False does not raise an exception and returns False if unable to check the task accessibility.

Raises:

wmflib.phabricator.PhabricatorError – if unable to verify if the task is accessible and raises is set to True.

Returns:

True if the task exists and is accessible by the current user, False if not accessible, an empty string was passed and allow_empty_identifiers is set to True or if unable to verify if the task is accessible and raises is set to False.

task_comment(task_id: str, comment: str, *, raises: bool = True) None[source]

Add a comment on a Phabricator task.

Examples:

>>> phab_client.task_comment("T12345", "Message")
>>> phab_client.task_comment("", "Message")  # with allow_empty_identifiers=True
DEBUG:wmflib.phabricator:No task specified, skipping task update with comment: Message
>>> phab_client.task_comment("", "Message", raises=False)  # with allow_empty_identifiers=True
DEBUG:wmflib.phabricator:No task specified, skipping task update with comment: Message
>>> phab_client.task_comment("T999999", "Message")
Traceback (most recent call last):
  [...SNIP...]
phabricator.APIError: ERR-CONDUIT-CORE: Monogram "T999999" does not identify a valid object.
  [...SNIP...]
wmflib.phabricator.PhabricatorError: Unable to update Phabricator task 'T999999'
>>> phab_client.task_comment("T999999", "Test comment", raises=False)
ERROR:wmflib.phabricator:Unable to update Phabricator task 'T999999' (raises=False): ERR-CONDUI[...SNIP...]
>>> phab_client.task_comment("T12345", "Message")  # with dry_run=True
DEBUG:wmflib.phabricator:Skip updating Phabricator task 'T12345' in DRY-RUN with comment: Message
Parameters:
  • task_id (str) – the Phabricator task ID (e.g. T12345) to be updated. If empty string no update will be sent and a debug log message will be logged.

  • comment (str) – the message to add to the task.

  • raises (bool) – if set to False does not raise an exception if unable to comment on the task.

Raises:

wmflib.phabricator.PhabricatorError – if unable to update the task and raises is set to True.

__dict__ = mappingproxy({'__module__': 'wmflib.phabricator', '__doc__': 'Class to interact with a Phabricator website.', '__init__': <function Phabricator.__init__>, 'task_accessible': <function Phabricator.task_accessible>, 'task_comment': <function Phabricator.task_comment>, '__dict__': <attribute '__dict__' of 'Phabricator' objects>, '__weakref__': <attribute '__weakref__' of 'Phabricator' objects>, '__annotations__': {}})
__doc__ = 'Class to interact with a Phabricator website.'
__module__ = 'wmflib.phabricator'
__weakref__

list of weak references to the object (if defined)