diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 8bfdf59..2a762b2 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -14,10 +14,10 @@ jobs: python-version: [3.6, 3.8, 3.9, "3.10"] steps: - name: Checkout Pylero - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set Up Python-${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} @@ -26,5 +26,7 @@ jobs: pip install -U pip pip install -U -r requirements.txt pip install . + - name: Pre Commit Checks - uses: pre-commit/action@v2.0.0 + uses: pre-commit/action@v3.0.0 + if: ${{ matrix.python-version != '3.6' }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e31f3c6..da45328 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,22 +1,18 @@ # configuration for pre-commit git hooks -files: ^(src/pylero) +exclude: '^docs' repos: - repo: https://github.com/asottile/reorder_python_imports - rev: v2.6.0 + rev: v3.8.2 hooks: - id: reorder-python-imports - language_version: python3 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.3.0 hooks: - id: trailing-whitespace - language_version: python3 - id: end-of-file-fixer - language_version: python3 - id: debug-statements - language_version: python3 -- repo: https://github.com/pycqa/flake8 - rev: 3.9.2 + - id: detect-private-key +- repo: https://github.com/psf/black + rev: 22.6.0 hooks: - - id: flake8 - language_version: python3 + - id: black diff --git a/README.md b/README.md index 97384c8..1438ad7 100644 --- a/README.md +++ b/README.md @@ -292,13 +292,13 @@ $ pip install pre-commit $ pre-commit autoupdate && pre-commit run -a ``` -Pre-commit will ensure that the changes you made are not in violation of PEP8 standards. +Pre-commit will ensure that the changes you made are not in violation of PEP8 standards and automatically apply black fixes. -We recommend `autopep8` to fix any pre-commit failures by running below or you are free to use any formatters which can resolve pre-commit failures with least possible diff. +We recommend `black` to automatically fix any pre-commit failures. ``` python -$ pip install autopep8 -$ autopep8 --in-place +$ pip install black +$ black ``` ## Fedora RPM package build diff --git a/doc/conf.py b/doc/conf.py index 225ff55..f7aee13 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -11,112 +11,116 @@ # # All configuration values have a default; values that are commented out # serve to show the default. - -import sys import os import shlex +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) -sys.path.insert(0, os.path.abspath('../src/..')) +# sys.path.insert(0, os.path.abspath('.')) +sys.path.insert(0, os.path.abspath("../src/..")) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.viewcode', - 'sphinx.ext.napoleon', - 'sphinx.ext.extlinks', + "sphinx.ext.autodoc", + "sphinx.ext.todo", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinx.ext.extlinks", ] -POLARION_URL = 'https://almdemo.polarion.com' -pol_client = '{}/polarion/sdk/doc/javadoc/com/polarion/alm/ws/client'.format(POLARION_URL) +POLARION_URL = "https://almdemo.polarion.com" +pol_client = "{}/polarion/sdk/doc/javadoc/com/polarion/alm/ws/client".format( + POLARION_URL +) extlinks = { - 'project': ('{}/projects/ProjectWebService.html#%s'.format(pol_client), ''), - 'tracker': ('{}/tracker/TrackerWebService.html#%s'.format(pol_client), ''), - 'testmanagement': ('{}/testmanagement/TestManagementWebService.html#%s'.format(pol_client), ''), - 'planning': ('{}/planning/PlanningWebService.html#%s'.format(pol_client), ''), - 'security': ('{}/security/SecurityWebService.html#%s'.format(pol_client), ''), - 'session': ('{}/session/SessionWebService.html#%s'.format(pol_client), ''), - 'builder': ('{}/builder/BuilderWebService.html#%s'.format(pol_client), '') + "project": ("{}/projects/ProjectWebService.html#%s".format(pol_client), ""), + "tracker": ("{}/tracker/TrackerWebService.html#%s".format(pol_client), ""), + "testmanagement": ( + "{}/testmanagement/TestManagementWebService.html#%s".format(pol_client), + "", + ), + "planning": ("{}/planning/PlanningWebService.html#%s".format(pol_client), ""), + "security": ("{}/security/SecurityWebService.html#%s".format(pol_client), ""), + "session": ("{}/session/SessionWebService.html#%s".format(pol_client), ""), + "builder": ("{}/builder/BuilderWebService.html#%s".format(pol_client), ""), } # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. -source_suffix = ['.rst'] +source_suffix = [".rst"] # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'pylero' -copyright = u'2021, Sim Zacks and Pylero Contributors' -author = u'Sim Zacks and Pylero Contributors' +project = "pylero" +copyright = "2021, Sim Zacks and Pylero Contributors" +author = "Sim Zacks and Pylero Contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.0.3' +version = "0.0.3" # The full version, including alpha/beta/rc tags. -release = '' +release = "" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = 'en' +language = "en" # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -126,31 +130,31 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -160,123 +164,123 @@ # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'pylerodoc' +htmlhelp_basename = "pylerodoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Latex figure (float) alignment + #'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'pylero.tex', u'pylero Documentation', - u'Author', 'manual', - u'Sim Zacks and Pylero Contributors', 'manual'), + ( + master_doc, + "pylero.tex", + "pylero Documentation", + "Author", + "manual", + "Sim Zacks and Pylero Contributors", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'pylero', u'pylero Documentation', - [author], 1) -] +man_pages = [(master_doc, "pylero", "pylero Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -285,22 +289,28 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'pylero', u'pylero Documentation', - author, 'pylero', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "pylero", + "pylero Documentation", + author, + "pylero", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False # -- Options for Epub output ---------------------------------------------- @@ -312,62 +322,62 @@ epub_copyright = copyright # The basename for the epub file. It defaults to the project name. -#epub_basename = project +# epub_basename = project # The HTML theme for the epub output. Since the default themes are not optimized # for small screen space, using the same theme for HTML and epub output is # usually not wise. This defaults to 'epub', a theme designed to save visual # space. -#epub_theme = 'epub' +# epub_theme = 'epub' # The language of the text. It defaults to the language option # or 'en' if the language is not set. -#epub_language = '' +# epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' +# epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. -#epub_identifier = '' +# epub_identifier = '' # A unique identification for the text. -#epub_uid = '' +# epub_uid = '' # A tuple containing the cover image and cover page html template filenames. -#epub_cover = () +# epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. -#epub_guide = () +# epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. -#epub_pre_files = [] +# epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. -#epub_post_files = [] +# epub_post_files = [] # A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +epub_exclude_files = ["search.html"] # The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 +# epub_tocdepth = 3 # Allow duplicate toc entries. -#epub_tocdup = True +# epub_tocdup = True # Choose between 'default' and 'includehidden'. -#epub_tocscope = 'default' +# epub_tocscope = 'default' # Fix unsupported image types using the Pillow. -#epub_fix_images = False +# epub_fix_images = False # Scale large images. -#epub_max_image_width = 0 +# epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. -#epub_show_urls = 'inline' +# epub_show_urls = 'inline' # If false, no index is generated. -#epub_use_index = True +# epub_use_index = True diff --git a/doc/index.rst b/doc/index.rst index 7e3d62a..1e26e6a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -302,4 +302,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/scripts/pylero b/scripts/pylero index 215e13c..c08d74a 100755 --- a/scripts/pylero +++ b/scripts/pylero @@ -22,19 +22,19 @@ else: def main(): - EXCLUDE_MODULES = ['test_classes', 'embedding', 'interface', 'server', - 'session'] + EXCLUDE_MODULES = ["test_classes", "embedding", "interface", "server", "session"] _class_names = [] for lstmods in pkgutil.iter_modules([pylero.__path__[0]]): the_mod = lstmods[1] if the_mod not in EXCLUDE_MODULES: - imp_mod = __import__("pylero.{0}".format(the_mod), fromlist=['']) + imp_mod = __import__("pylero.{0}".format(the_mod), fromlist=[""]) for cls in inspect.getmembers(imp_mod, inspect.isclass): globals()[cls[0]] = cls[1] if cls[0] not in _class_names: _class_names.append(cls[0]) _class_names.sort() + if __name__ == "__main__": main() - os.environ['PYTHONINSPECT'] = "yes" + os.environ["PYTHONINSPECT"] = "yes" diff --git a/scripts/pylero-cmd b/scripts/pylero-cmd index e08aa16..005e6fe 100755 --- a/scripts/pylero-cmd +++ b/scripts/pylero-cmd @@ -10,53 +10,64 @@ def cli(): @cli.command() -@click.option('-d', '--document', - help="document with space e.g. 'space/document'") -@click.option('-e', '--query', - help="query items e.g. --query='author.id:xhe'") -@click.option('-D', '--is_document', - default=False, - is_flag=True, - help='flag indicating that the action will reference a document') -@click.option('-i', '--testcase', - help='testcase id') -@click.option('-l', '--links', - default=False, - is_flag=True, - help='flag indicating that the action will reference the links') -@click.option('-m', '--template', - default=False, - is_flag=True, - help='flag indicating that the action will reference a template') -@click.option('-p', '--plan_ids', - help='plan ids in project') -@click.option('-q', '--requirement', - help='requirement id') -@click.option('-r', '--run', - help='test run') -@click.option('-s', '--steps', - default=False, - is_flag=True, - help='flag indicating that the action will reference the steps') -@click.option('-t', '--workitem', - default=False, - is_flag=True, - help='flag indicating that the action will reference workitem') -@click.option('-w', '--wi_type', - default='', - help="type of workitem. e.g testcase, requirement") -def list(document, - query, - is_document, - testcase, - links, - template, - plan_ids, - requirement, - run, - steps, - workitem, - wi_type=None): +@click.option("-d", "--document", help="document with space e.g. 'space/document'") +@click.option("-e", "--query", help="query items e.g. --query='author.id:xhe'") +@click.option( + "-D", + "--is_document", + default=False, + is_flag=True, + help="flag indicating that the action will reference a document", +) +@click.option("-i", "--testcase", help="testcase id") +@click.option( + "-l", + "--links", + default=False, + is_flag=True, + help="flag indicating that the action will reference the links", +) +@click.option( + "-m", + "--template", + default=False, + is_flag=True, + help="flag indicating that the action will reference a template", +) +@click.option("-p", "--plan_ids", help="plan ids in project") +@click.option("-q", "--requirement", help="requirement id") +@click.option("-r", "--run", help="test run") +@click.option( + "-s", + "--steps", + default=False, + is_flag=True, + help="flag indicating that the action will reference the steps", +) +@click.option( + "-t", + "--workitem", + default=False, + is_flag=True, + help="flag indicating that the action will reference workitem", +) +@click.option( + "-w", "--wi_type", default="", help="type of workitem. e.g testcase, requirement" +) +def list( + document, + query, + is_document, + testcase, + links, + template, + plan_ids, + requirement, + run, + steps, + workitem, + wi_type=None, +): """list documents, testcases, steps of testcase, links of workitems, runs templates.""" @@ -106,80 +117,84 @@ def list(document, list_obj.print_plan_ids(plan_ids) else: - click.echo('Please get usage: pylero-cmd list --help') + click.echo("Please get usage: pylero-cmd list --help") @cli.command() -@click.option("-a", "--assignee", default="None", - help="assignee of run") -@click.option("-c", "--comment", - help="verdict comment of testcase in run") -@click.option("-d", "--description", - help="description of run") -@click.option("-e", "--query", - help="query items e.g. --query=author.id:xhe") -@click.option("-g", "--is_document", - default=False, - is_flag=True, - help='flag indicating that the action will reference a document') -@click.option("-p", "--doc_with_space", - help="document id with space e.g --doc_with_space=KernelQE/DOC") -@click.option("-b", "--doc_type", - type=click.Choice(['generic', - 'testspecification', - 'requirementspecification']), - default='generic', - help="document type, default='generic'") -@click.option("-g", "--doc_wi_type", - type=click.Choice(['testcase', - 'requirement']), - default='testcase', - help="allowed workitem type in document, default='testcase'") -@click.option("-f", "--doc_content", - default='My sample document', - help="HTML markup to document, default='My sample\ +@click.option("-a", "--assignee", default="None", help="assignee of run") +@click.option("-c", "--comment", help="verdict comment of testcase in run") +@click.option("-d", "--description", help="description of run") +@click.option("-e", "--query", help="query items e.g. --query=author.id:xhe") +@click.option( + "-g", + "--is_document", + default=False, + is_flag=True, + help="flag indicating that the action will reference a document", +) +@click.option( + "-p", + "--doc_with_space", + help="document id with space e.g --doc_with_space=KernelQE/DOC", +) +@click.option( + "-b", + "--doc_type", + type=click.Choice(["generic", "testspecification", "requirementspecification"]), + default="generic", + help="document type, default='generic'", +) +@click.option( + "-g", + "--doc_wi_type", + type=click.Choice(["testcase", "requirement"]), + default="testcase", + help="allowed workitem type in document, default='testcase'", +) +@click.option( + "-f", + "--doc_content", + default="My sample document", + help="HTML markup to document, default='My sample\ document'. It can be a html file e.g\ - --doc_content=/home/xhe/plan.html") -@click.option('-D', '--debug', - default=True, - is_flag=True, - help='debug mode') -@click.option("-i", "--testcase", - help="testcase id") -@click.option("-m", "--template", - help="run template") -@click.option("-p", "--plannedin", - help="plannedin in run") -@click.option("-o", "--result", - type=click.Choice(['passed', - 'failed', - 'blocked']), - help="test result in run") -@click.option("-r", "--run", - help="test run id") -@click.option("-s", "--status", - type=click.Choice(['notrun', - 'inprogress', - 'finished', - 'invalid']), - help="run status") -def update(assignee, - comment, - description, - query, - is_document, - doc_with_space, - doc_type, - doc_wi_type, - doc_content, - debug, - testcase, - template, - plannedin, - result, - run, - status): - ''' create run(s), update results and custom fileds for run(s). ''' + --doc_content=/home/xhe/plan.html", +) +@click.option("-D", "--debug", default=True, is_flag=True, help="debug mode") +@click.option("-i", "--testcase", help="testcase id") +@click.option("-m", "--template", help="run template") +@click.option("-p", "--plannedin", help="plannedin in run") +@click.option( + "-o", + "--result", + type=click.Choice(["passed", "failed", "blocked"]), + help="test result in run", +) +@click.option("-r", "--run", help="test run id") +@click.option( + "-s", + "--status", + type=click.Choice(["notrun", "inprogress", "finished", "invalid"]), + help="run status", +) +def update( + assignee, + comment, + description, + query, + is_document, + doc_with_space, + doc_type, + doc_wi_type, + doc_content, + debug, + testcase, + template, + plannedin, + result, + run, + status, +): + """create run(s), update results and custom fileds for run(s).""" # instantiate the update object update_obj = CmdUpdate() @@ -188,12 +203,12 @@ def update(assignee, if not doc_with_space: print("Exit - Missing value of --doc_with_space") return False - if '/' not in doc_with_space: + if "/" not in doc_with_space: print("Exit - 'SPACE/DOC_NAME' is required, --doc_with_space") return False # split string of doc_with_space - doc_space_list = doc_with_space.split('/') + doc_space_list = doc_with_space.split("/") space = doc_space_list[0] doc_name = doc_space_list[1] @@ -201,35 +216,30 @@ def update(assignee, doc_title = doc_name # create document from string or html file - update_obj.update_document(space, doc_name, doc_title, doc_wi_type, - doc_type, "parent", doc_content) + update_obj.update_document( + space, doc_name, doc_title, doc_wi_type, doc_type, "parent", doc_content + ) elif run: if result: if testcase: # update one case result for runs - update_obj.update_1_case_result_for_run(run, - testcase, - result, - assignee, - comment) + update_obj.update_1_case_result_for_run( + run, testcase, result, assignee, comment + ) else: # update all case results for runs - update_obj.update_all_case_results_for_runs(run, - result, - assignee, - comment) + update_obj.update_all_case_results_for_runs( + run, result, assignee, comment + ) else: # update/create runs - update_obj.update_runs(run, - template, - plannedin, - assignee, - status, - description) + update_obj.update_runs( + run, template, plannedin, assignee, status, description + ) else: - click.echo('Please get usage: pylero-cmd update --help') + click.echo("Please get usage: pylero-cmd update --help") -if __name__ == '__main__': +if __name__ == "__main__": cli() diff --git a/src/pylero/_compatible.py b/src/pylero/_compatible.py index 97bb112..627346a 100644 --- a/src/pylero/_compatible.py +++ b/src/pylero/_compatible.py @@ -34,7 +34,7 @@ try: string_types = (str, unicode) except NameError: - string_types = (str, ) + string_types = (str,) try: from __builtin__ import basestring diff --git a/src/pylero/activity.py b/src/pylero/activity.py index 060de67..fb9b1f0 100644 --- a/src/pylero/activity.py +++ b/src/pylero/activity.py @@ -23,22 +23,22 @@ class Activity(BasePolarion): source_id (string) timestamp (dateTime) type (string) - user_id (string) -""" - _cls_suds_map = {"activity_custom_values": "activity_custom_values", - "comments": "comments", # array of ActivityComment - "global_id": "globalId", - "activity_id": "id", - "info": - {"field_name": "info", - "cls": Text}, - "prefix": "prefix", - "resource_locations": "resourceLocations", - "source_id": "sourceId", - "timestamp": "timestamp", - "type": "type", - "user_id": "userId", - "uri": "_uri", - "_unresolved": "_unresolved"} + user_id (string)""" + + _cls_suds_map = { + "activity_custom_values": "activity_custom_values", + "comments": "comments", # array of ActivityComment + "global_id": "globalId", + "activity_id": "id", + "info": {"field_name": "info", "cls": Text}, + "prefix": "prefix", + "resource_locations": "resourceLocations", + "source_id": "sourceId", + "timestamp": "timestamp", + "type": "type", + "user_id": "userId", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:Activity" diff --git a/src/pylero/activity_comment.py b/src/pylero/activity_comment.py index 8ab7918..6865b2c 100644 --- a/src/pylero/activity_comment.py +++ b/src/pylero/activity_comment.py @@ -16,10 +16,11 @@ class ActivityComment(BasePolarion): time_stamp (dateאime) user_id (string) """ - _cls_suds_map = {"text": - {"field_name": "text", - "cls": Text}, - "time_stamp": "timeStamp", - "user_id": "userId"} + + _cls_suds_map = { + "text": {"field_name": "text", "cls": Text}, + "time_stamp": "timeStamp", + "user_id": "userId", + } _obj_client = "tracker_client" _obj_struct = "tns3:ActivityComment" diff --git a/src/pylero/activity_custom_value.py b/src/pylero/activity_custom_value.py index 0c24ece..7e0817a 100644 --- a/src/pylero/activity_custom_value.py +++ b/src/pylero/activity_custom_value.py @@ -11,10 +11,8 @@ class ActivityCustomValue(BasePolarion): """Object to handle the Polarion WSDL tns3:ActivityCustomValue class Attributes: - values (ArrayOf_xsd_string) -""" - _cls_suds_map = {"values": "values", - "uri": "_uri", - "_unresolved": "_unresolved"} + values (ArrayOf_xsd_string)""" + + _cls_suds_map = {"values": "values", "uri": "_uri", "_unresolved": "_unresolved"} _obj_client = "tracker_client" _obj_struct = "tns3:ActivityCustomValue" diff --git a/src/pylero/activity_custom_value_entry.py b/src/pylero/activity_custom_value_entry.py index 0f77971..a758450 100644 --- a/src/pylero/activity_custom_value_entry.py +++ b/src/pylero/activity_custom_value_entry.py @@ -13,13 +13,13 @@ class ActivityCustomValueEntry(BasePolarion): Attributes: custom_values (ActivityCustomValue) - key (string) -""" - _cls_suds_map = {"custom_values": - {"field_name": "customValues", - "cls": ActivityCustomValue}, - "key": "key", - "uri": "_uri", - "_unresolved": "_unresolved"} + key (string)""" + + _cls_suds_map = { + "custom_values": {"field_name": "customValues", "cls": ActivityCustomValue}, + "key": "key", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:ActivityCustomValueEntry" diff --git a/src/pylero/activity_source.py b/src/pylero/activity_source.py index 860d157..a5dac40 100644 --- a/src/pylero/activity_source.py +++ b/src/pylero/activity_source.py @@ -13,12 +13,14 @@ class ActivitySource(BasePolarion): Attributes: activity_source_id (string) prefix (string) - types (ArrayOf_xsd_string) -""" - _cls_suds_map = {"activity_source_id": "id", - "prefix": "prefix", - "types": "types", - "uri": "_uri", - "_unresolved": "_unresolved"} + types (ArrayOf_xsd_string)""" + + _cls_suds_map = { + "activity_source_id": "id", + "prefix": "prefix", + "types": "types", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:ActivitySource" diff --git a/src/pylero/approval.py b/src/pylero/approval.py index 59adc0a..68d1288 100644 --- a/src/pylero/approval.py +++ b/src/pylero/approval.py @@ -14,18 +14,18 @@ class Approval(BasePolarion): Attributes: status (EnumOptionId) - user (User) -""" + user (User)""" + _cls_suds_map = { - "status": - {"field_name": "status", - "cls": EnumOptionId, - "enum_id": "approval-status"}, - "user_id": - {"field_name": "user", - "cls": User}, + "status": { + "field_name": "status", + "cls": EnumOptionId, + "enum_id": "approval-status", + }, + "user_id": {"field_name": "user", "cls": User}, "uri": "_uri", - "_unresolved": "_unresolved"} + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:Approval" diff --git a/src/pylero/attachment.py b/src/pylero/attachment.py index 0a47cee..c42ebed 100644 --- a/src/pylero/attachment.py +++ b/src/pylero/attachment.py @@ -18,19 +18,19 @@ class Attachment(BasePolarion): length (long) title (string) updated (dateTime) - url (string) -""" - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "file_name": "fileName", - "attachment_id": "id", - "length": "length", - "title": "title", - "updated": "updated", - "url": "url", - "uri": "_uri", - "_unresolved": "_unresolved"} + url (string)""" + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "file_name": "fileName", + "attachment_id": "id", + "length": "length", + "title": "title", + "updated": "updated", + "url": "url", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:Attachment" diff --git a/src/pylero/base_polarion.py b/src/pylero/base_polarion.py index 988f1fc..a64e3b5 100644 --- a/src/pylero/base_polarion.py +++ b/src/pylero/base_polarion.py @@ -40,63 +40,78 @@ class Configuration(object): # https://docs.python.org/2.6/library/configparser.html def __init__(self): - defaults = {"cachingpolicy": "0", - "timeout": "120"} + defaults = {"cachingpolicy": "0", "timeout": "120"} config = ConfigParser(defaults) # Check for existence of config file and config_section - if not config.read([self.GLOBAL_CONFIG, self.LOCAL_CONFIG, - self.CURDIR_CONFIG]) or \ - not config.has_section(self.CONFIG_SECTION): + if not config.read( + [self.GLOBAL_CONFIG, self.LOCAL_CONFIG, self.CURDIR_CONFIG] + ) or not config.has_section(self.CONFIG_SECTION): # Check for mandatory environ variables if config file is not found - if not all(os.environ.get(item) for item in ('POLARION_URL', - 'POLARION_REPO', - 'POLARION_USERNAME', - 'POLARION_PASSWORD', - 'POLARION_PROJECT')): - raise PyleroLibException("The config files/ENV vars do not " - "exist or are not of the correct " - "format. Valid files are: {0}, {1} " - "or {2}" .format(self.GLOBAL_CONFIG, - self.LOCAL_CONFIG, - self.CURDIR_CONFIG)) - self.server_url = os.environ.get("POLARION_URL") or \ - config.get(self.CONFIG_SECTION, "url") - self.repo = os.environ.get("POLARION_REPO") or \ - config.get(self.CONFIG_SECTION, "svn_repo") - self.login = os.environ.get("POLARION_USERNAME") or \ - config.get(self.CONFIG_SECTION, "user") - self.pwd = os.environ.get("POLARION_PASSWORD") or \ - config.get(self.CONFIG_SECTION, "password") + if not all( + os.environ.get(item) + for item in ( + "POLARION_URL", + "POLARION_REPO", + "POLARION_USERNAME", + "POLARION_PASSWORD", + "POLARION_PROJECT", + ) + ): + raise PyleroLibException( + "The config files/ENV vars do not " + "exist or are not of the correct " + "format. Valid files are: {0}, {1} " + "or {2}".format( + self.GLOBAL_CONFIG, self.LOCAL_CONFIG, self.CURDIR_CONFIG + ) + ) + self.server_url = os.environ.get("POLARION_URL") or config.get( + self.CONFIG_SECTION, "url" + ) + self.repo = os.environ.get("POLARION_REPO") or config.get( + self.CONFIG_SECTION, "svn_repo" + ) + self.login = os.environ.get("POLARION_USERNAME") or config.get( + self.CONFIG_SECTION, "user" + ) + self.pwd = os.environ.get("POLARION_PASSWORD") or config.get( + self.CONFIG_SECTION, "password" + ) try: - self.timeout = os.environ.get("POLARION_TIMEOUT") or \ - config.get(self.CONFIG_SECTION, "timeout") + self.timeout = os.environ.get("POLARION_TIMEOUT") or config.get( + self.CONFIG_SECTION, "timeout" + ) except Exception: - self.timeout = config.defaults['timeout'] + self.timeout = config.defaults["timeout"] try: self.timeout = int(self.timeout) except ValueError: - raise PyleroLibException("The timeout value in the config" - " file must be an integer") - self.proj = os.environ.get("POLARION_PROJECT") or \ - config.get(self.CONFIG_SECTION, "default_project") + raise PyleroLibException( + "The timeout value in the config" " file must be an integer" + ) + self.proj = os.environ.get("POLARION_PROJECT") or config.get( + self.CONFIG_SECTION, "default_project" + ) try: - self.cert_path = os.environ.get("POLARION_CERT_PATH") or \ - config.get(self.CONFIG_SECTION, "cert_path") + self.cert_path = os.environ.get("POLARION_CERT_PATH") or config.get( + self.CONFIG_SECTION, "cert_path" + ) except Exception: self.cert_path = None if not (self.server_url and self.login and self.proj): - raise PyleroLibException("The config files must contain " - "valid values for: url, user, " - "password and default_project") + raise PyleroLibException( + "The config files must contain " + "valid values for: url, user, " + "password and default_project" + ) try: - self.disable_manual_auth = \ - os.environ.get("POLARION_DISABLE_MANUAL_AUTH") or \ - config.getboolean(self.CONFIG_SECTION, - "disable_manual_auth") + self.disable_manual_auth = os.environ.get( + "POLARION_DISABLE_MANUAL_AUTH" + ) or config.getboolean(self.CONFIG_SECTION, "disable_manual_auth") except Exception: self.disable_manual_auth = False @@ -115,6 +130,7 @@ class Connection(object): POLARION_TIMEOUT POLARION_PROJECT """ + connected = False session = None password_retries = 3 @@ -126,15 +142,16 @@ def session(cls): # if the password is not supplied in the config file, ask the user # for it if not cfg.pwd: - cfg.pwd = getpass( - "Password not in config file.\nEnter Password:") + cfg.pwd = getpass("Password not in config file.\nEnter Password:") while not cls.connected and cls.password_retries: try: srv = Server( cfg.server_url, - cfg.login, cfg.pwd, + cfg.login, + cfg.pwd, timeout=cfg.timeout, - cert_path=cfg.cert_path) + cert_path=cfg.cert_path, + ) cls.session = srv.session() cls.session._login() cls.connected = True @@ -142,19 +159,23 @@ def session(cls): # If we couldn't connect its because the user has typed the # wrong password. So we keep asking for password till we # are successfully connected - if "com.polarion.platform.security." \ - "AuthenticationFailedException" \ - in e.fault.faultstring: + if ( + "com.polarion.platform.security." + "AuthenticationFailedException" in e.fault.faultstring + ): if cfg.disable_manual_auth: - raise PyleroLibException("Manual authentication " - "is disabled") + raise PyleroLibException( + "Manual authentication " "is disabled" + ) cfg.pwd = getpass("Invalid Password.\nEnter Password:") cls.password_retries -= 1 else: raise if not cls.password_retries: - raise PyleroLibException("Unable to establish pylero session " - "due to 3 incorrect login attempts") + raise PyleroLibException( + "Unable to establish pylero session " + "due to 3 incorrect login attempts" + ) cls.session.default_project = cfg.proj cls.session.user_id = cfg.login cls.session.password = cfg.pwd @@ -186,6 +207,7 @@ def inner(*args, **kwargs): if new_tx and self.session.tx_in(): self.session.tx_rollback() raise + return inner @@ -218,25 +240,21 @@ class BasePolarion(object): default_project (str): The user's default project, to be used when project_id is needed and there is none given """ + _cls_suds_map = {} _id_field = None _obj_client = None _obj_struct = None _session = None _default_project = None - _cache = { - "enums": {}, - "custom_field_types": {}, - "projects": {} - } + _cache = {"enums": {}, "custom_field_types": {}, "projects": {}} REGEX_PROJ = r"/default/(.*)\$" # The id in the uri is always after the last }, at times there are multiple REGEX_ID = ".+}(.*)$" # The URI_STRUCT can be overridden in a child class when needed (for # example, Documents). Also if there is need for a replace in the child # class the URI_ID lambda attributes should be overridden - URI_STRUCT = "subterra:data-service:objects:/default/" \ - "%(project)s${%(obj)s}%(id)s" + URI_STRUCT = "subterra:data-service:objects:/default/" "%(project)s${%(obj)s}%(id)s" # must wrap lambda with classmethod so it can be used as such URI_ID_GET_REPLACE = classmethod(lambda cls, x: x) URI_ID_SET_REPLACE = classmethod(lambda cls, x: x) @@ -285,17 +303,21 @@ def _convert_obj_fields_to_polarion(cls, fields=[]): if not isinstance(fields, list): fields = [fields] # convert given fields to Polarion fields - p_fields = ["%s%s" % ( - "customFields." - if isinstance(cls._cls_suds_map[x], dict) and - cls._cls_suds_map[x].get("is_custom", False) - else "", - cls._cls_suds_map[x] - if not isinstance(cls._cls_suds_map[x], dict) - else cls._cls_suds_map[x]["field_name"]) for x in fields] + p_fields = [ + "%s%s" + % ( + "customFields." + if isinstance(cls._cls_suds_map[x], dict) + and cls._cls_suds_map[x].get("is_custom", False) + else "", + cls._cls_suds_map[x] + if not isinstance(cls._cls_suds_map[x], dict) + else cls._cls_suds_map[x]["field_name"], + ) + for x in fields + ] # Omit 'URIs' and 'URI' from URIFields - p_fields = [(x.replace("URIs", "").replace("URI", "")) - for x in p_fields] + p_fields = [(x.replace("URIs", "").replace("URI", "")) for x in p_fields] return p_fields @classmethod @@ -329,7 +351,8 @@ def has_current_user_permission(cls, permission, project_id): Security.hasCurrentUserPermission """ return cls.session.security_client.service.hasCurrentuserPermission( - permission, project_id) + permission, project_id + ) def __init__(self, obj_id=None, suds_object=None): # cls_suds_map must be available for some parameters on the class @@ -348,7 +371,9 @@ def __init__(self, obj_id=None, suds_object=None): if obj_id and not self._id_field: raise PyleroLibException( "{0} only accepts a suds object, not an obj_id".format( - self.__class__.__name)) + self.__class__.__name + ) + ) if suds_object: self._suds_object = suds_object else: @@ -384,40 +409,69 @@ def __init__(self, obj_id=None, suds_object=None): # use getattr and setattr if isinstance(self._cls_suds_map[key], dict): if "is_custom" in self._cls_suds_map[key]: - setattr(self.__class__, key, property( - lambda self, field_name=key: - self._custom_getter(field_name), - lambda self, val, field_name=key: - self._custom_setter(val, field_name))) + setattr( + self.__class__, + key, + property( + lambda self, field_name=key: self._custom_getter( + field_name + ), + lambda self, val, field_name=key: self._custom_setter( + val, field_name + ), + ), + ) elif "is_array" in self._cls_suds_map[key]: - setattr(self.__class__, key, property( - lambda self, field_name=key: - self._arr_obj_getter(field_name), - lambda self, val, field_name=key: - self._arr_obj_setter(val, field_name))) + setattr( + self.__class__, + key, + property( + lambda self, field_name=key: self._arr_obj_getter( + field_name + ), + lambda self, val, field_name=key: self._arr_obj_setter( + val, field_name + ), + ), + ) else: - setattr(self.__class__, key, property( - lambda self, field_name=key: - self._obj_getter(field_name), - lambda self, val, field_name=key: - self._obj_setter(val, field_name))) + setattr( + self.__class__, + key, + property( + lambda self, field_name=key: self._obj_getter( + field_name + ), + lambda self, val, field_name=key: self._obj_setter( + val, field_name + ), + ), + ) else: - setattr(self.__class__, key, property( - # if the attribute doesn't exist in the current object - # return None - lambda self, suds_key=self._cls_suds_map[key]: - getattr(self._suds_object, suds_key, None), - lambda self, value, suds_key=self._cls_suds_map[key]: - self._regular_setter(value, suds_key))) -# after all properties are defined set the id field to the value passed in. + setattr( + self.__class__, + key, + property( + # if the attribute doesn't exist in the current object + # return None + lambda self, suds_key=self._cls_suds_map[key]: getattr( + self._suds_object, suds_key, None + ), + lambda self, value, suds_key=self._cls_suds_map[ + key + ]: self._regular_setter(value, suds_key), + ), + ) + # after all properties are defined set the id field to the value passed in. if obj_id is not None: setattr(self, self._id_field, obj_id) def _get_suds_object(self): """Returns the WSDL object as created by the Polarion WSDL factory""" if self._obj_client and self._obj_struct: - self._suds_object = getattr(self.session, self._obj_client). \ - factory.create(self._obj_struct) + self._suds_object = getattr(self.session, self._obj_client).factory.create( + self._obj_struct + ) else: self._suds_object = None @@ -433,8 +487,7 @@ def _obj_getter(self, field_name): """ csm = self._cls_suds_map[field_name] named_arg = csm.get("named_arg", "suds_object") - suds_field_val = getattr( - self._suds_object, csm.get("field_name", ""), None) + suds_field_val = getattr(self._suds_object, csm.get("field_name", ""), None) cls_obj = csm["cls"] if suds_field_val: if named_arg == "uri" and cls_obj._id_field: @@ -474,18 +527,19 @@ def _obj_setter(self, val, field_name): val = self._check_encode(val) if enum_id and val not in enum_override: self.check_valid_field_values( - val, enum_id, {}, - self._wi_type if hasattr(self, "_wi_type") else None) + val, + enum_id, + {}, + self._wi_type if hasattr(self, "_wi_type") else None, + ) if not sync_field: sync_field = "_suds_object" if isinstance(val, basestring) or val is None: add_parms[obj_cls._id_field] = val obj = obj_cls(**add_parms) - setattr(self._suds_object, suds_field_name, - getattr(obj, sync_field)) + setattr(self._suds_object, suds_field_name, getattr(obj, sync_field)) elif isinstance(val, obj_cls): - setattr(self._suds_object, suds_field_name, - getattr(val, sync_field)) + setattr(self._suds_object, suds_field_name, getattr(val, sync_field)) elif isinstance(val, obj_cls()._suds_object.__class__): obj = obj_cls() if sync_field in obj._cls_suds_map: @@ -494,8 +548,7 @@ def _obj_setter(self, val, field_name): val = getattr(val, suds_sync_field) setattr(self._suds_object, suds_field_name, val) else: - raise PyleroLibException("the value {0} is not a valid type". - format(val)) + raise PyleroLibException("the value {0} is not a valid type".format(val)) def _arr_obj_getter(self, field_name): """get function for attributes that reference an array of objects. @@ -532,15 +585,14 @@ def _arr_obj_setter(self, val, field_name): arr_inst = csm.get("arr_cls")() obj_inst = csm.get("cls")() # obj_attach = - if not isinstance(val, - (list, arr_inst.__class__, - arr_inst._suds_object.__class__)): - raise PyleroLibException( - "{0}s must be a list of {1}").format( - csm["field_name"], obj_inst.__class__.__name__) + if not isinstance( + val, (list, arr_inst.__class__, arr_inst._suds_object.__class__) + ): + raise PyleroLibException("{0}s must be a list of {1}").format( + csm["field_name"], obj_inst.__class__.__name__ + ) elif not val: - setattr( - self._suds_object, csm["field_name"], arr_inst._suds_object) + setattr(self._suds_object, csm["field_name"], arr_inst._suds_object) elif isinstance(val, arr_inst._suds_object.__class__): setattr(self._suds_object, csm["field_name"], val) elif isinstance(val, arr_inst.__class__): @@ -554,27 +606,28 @@ def _arr_obj_setter(self, val, field_name): val = [csm["cls"](item) for item in val] if isinstance(val[0], obj_inst._suds_object.__class__): - setattr(getattr(self._suds_object, csm["field_name"]), - csm["inner_field_name"], val) + setattr( + getattr(self._suds_object, csm["field_name"]), + csm["inner_field_name"], + val, + ) else: - setattr(self._suds_object, csm["field_name"], - arr_inst._suds_object) + setattr(self._suds_object, csm["field_name"], arr_inst._suds_object) for item in val: - getattr(getattr(self._suds_object, csm["field_name"]), - csm["inner_field_name"]).append( - item._suds_object) + getattr( + getattr(self._suds_object, csm["field_name"]), + csm["inner_field_name"], + ).append(item._suds_object) def custom_obj(self): # This returns a custom Polarion object. It can't use the Custom class # as that is a child of this class. - return self.session.test_management_client.factory.create( - "tns4:Custom") + return self.session.test_management_client.factory.create("tns4:Custom") def custom_array_obj(self): # This returns a custom Polarion object. It can't use the Custom class # as that is a child of this class. - return self.session.test_management_client.factory.create( - "tns4:ArrayOfCustom") + return self.session.test_management_client.factory.create("tns4:ArrayOfCustom") def _custom_getter(self, field_name): """Works with custom fields that has attributes stored differently @@ -591,15 +644,15 @@ def _custom_getter(self, field_name): csm = self._cls_suds_map[field_name] if field_name == "test_steps": if self._changed_fields.get("testSteps"): - return csm["cls"]( - suds_object=self._changed_fields.get("testSteps")) + return csm["cls"](suds_object=self._changed_fields.get("testSteps")) else: test_steps = self.get_test_steps() if test_steps: return test_steps else: - if (("customFields" not in self._suds_object) or - (not self._suds_object.customFields)): + if ("customFields" not in self._suds_object) or ( + not self._suds_object.customFields + ): self._suds_object.customFields = self.custom_array_obj() cf = self._suds_object.customFields[0] custom_fld = None @@ -609,8 +662,7 @@ def _custom_getter(self, field_name): if match: custom_fld = match[0] if not custom_fld and self.uri: - custom_fld = self.get_custom_field( - csm["field_name"])._suds_object + custom_fld = self.get_custom_field(csm["field_name"])._suds_object if custom_fld: if isinstance(custom_fld, basestring): obj = custom_fld @@ -620,13 +672,10 @@ def _custom_getter(self, field_name): if custom_fld.value: for inst in custom_fld.value[0]: if csm["cls"]._cls_inner._id_field: - item_inst = csm["cls"]._cls_inner( - suds_object=inst) - obj.append( - getattr(item_inst, item_inst._id_field)) + item_inst = csm["cls"]._cls_inner(suds_object=inst) + obj.append(getattr(item_inst, item_inst._id_field)) else: - obj.append(csm["cls"]._cls_inner( - suds_object=inst)) + obj.append(csm["cls"]._cls_inner(suds_object=inst)) elif csm.get("cls"): obj = csm["cls"](suds_object=custom_fld.value) else: @@ -657,7 +706,8 @@ def _custom_setter(self, val, field_name): self._changed_fields[csm["field_name"]] = val else: raise PyleroLibException( - "The value must be a {0}".format(csm["cls"].__name__)) + "The value must be a {0}".format(csm["cls"].__name__) + ) # move the custom fields to within the object, otherwise each custom # field is a seperate SVN commit. testSteps, does not work unless it # is uploaded using the set_test_steps function. @@ -666,22 +716,20 @@ def _custom_setter(self, val, field_name): cust.key = csm["field_name"] if val is None: cust.value = None - elif (not csm.get("cls") or isinstance(val, basestring)) \ - and not csm.get("is_array"): + elif (not csm.get("cls") or isinstance(val, basestring)) and not csm.get( + "is_array" + ): # if there is no cls specified, val can be a bool, int, ... # if val is a string, it may be used to instantiate the class if isinstance(val, basestring): val = self._check_encode(val) - if csm.get("enum_id") and \ - val not in csm.get("enum_override", []): + if csm.get("enum_id") and val not in csm.get("enum_override", []): # uses deepcopy, to not affect other instances of the class - additional_parms = copy.deepcopy( - csm.get("additional_parms", {})) - self.check_valid_field_values(val, csm.get("enum_id"), - additional_parms, - csm.get("control")) - cust.value = csm["cls"](val)._suds_object if csm.get("cls") \ - else val + additional_parms = copy.deepcopy(csm.get("additional_parms", {})) + self.check_valid_field_values( + val, csm.get("enum_id"), additional_parms, csm.get("control") + ) + cust.value = csm["cls"](val)._suds_object if csm.get("cls") else val elif csm.get("is_array"): if not isinstance(val, list): raise PyleroLibException("value must be a list") @@ -692,13 +740,15 @@ def _custom_setter(self, val, field_name): # uses deepcopy, to not affect other instances # of the class additional_parms = copy.deepcopy( - csm.get("additional_parms", {})) + csm.get("additional_parms", {}) + ) self.check_valid_field_values( - i, csm.get("enum_id"), additional_parms, - self._wi_type if hasattr(self, "_wi_type") - else None) - cust.value[0].append( - csm["cls"]._cls_inner(i)._suds_object) + i, + csm.get("enum_id"), + additional_parms, + self._wi_type if hasattr(self, "_wi_type") else None, + ) + cust.value[0].append(csm["cls"]._cls_inner(i)._suds_object) elif isinstance(val, csm["cls"]): cust.value = val._suds_object @@ -706,10 +756,11 @@ def _custom_setter(self, val, field_name): cust.value = val else: raise PyleroLibException( - "The value must be of type {0}." - .format(csm["cls"].__name__)) - if (("customFields" not in self._suds_object) or - (not self._suds_object.customFields)): + "The value must be of type {0}.".format(csm["cls"].__name__) + ) + if ("customFields" not in self._suds_object) or ( + not self._suds_object.customFields + ): self._suds_object.customFields = self.custom_array_obj() cf = self._suds_object.customFields[0] if cf: @@ -746,15 +797,14 @@ def _check_encode(self, val): val (string): the value that the property is being set to """ try: - if not isinstance(val, type(u'')): - val = val.decode('utf-8') + if not isinstance(val, type("")): + val = val.decode("utf-8") # replace chr(160) with space - return val.replace(u'\xa0', u' ') + return val.replace("\xa0", " ") except UnicodeError as err: raise PyleroLibException( - 'String must be UTF-8 encoded. The following error was ' - 'raised when converting it to unicode: {0}' - .format(err) + "String must be UTF-8 encoded. The following error was " + "raised when converting it to unicode: {0}".format(err) ) def _get_file_data(self, path): @@ -775,18 +825,19 @@ def _get_file_data(self, path): # Effectively turns in Python3 String try: # Python2 - return bencode.encode('utf8') + return bencode.encode("utf8") except AttributeError: # Python3 - return bencode.decode('utf8') + return bencode.decode("utf8") def _verify_obj(self): # verifies if the object contains a suds object from the server by # checking if the uri field is populated. If no URI it didn't come from # the server if not getattr(self, "uri", None): - raise PyleroLibException("There is no {0} loaded".format( - self.__class__.__name__)) + raise PyleroLibException( + "There is no {0} loaded".format(self.__class__.__name__) + ) def can_add_element_to_key(self, key): """Checks if the current user can add elements to the collection at @@ -802,8 +853,7 @@ def can_add_element_to_key(self, key): Security.canAddElementToKey """ self._verify_obj() - return self.session.security_client.service.canAddElementToKey( - self.uri, key) + return self.session.security_client.service.canAddElementToKey(self.uri, key) def can_delete_instance(self): """Checks if the current user can delete the current object @@ -897,7 +947,8 @@ def can_remove_element_from_key(self, key): """ self._verify_obj() return self.session.security_client.service.canRemoveElementFromKey( - self.uri, key) + self.uri, key + ) def get_location(self): """Returns the location of the current object. In the context of this @@ -916,8 +967,7 @@ def get_location(self): self._verify_obj() return self.session.security_client.service.getLocationForURI(self.uri) - def check_valid_field_values(self, val, enum_id, additional_parms, - control=None): + def check_valid_field_values(self, val, enum_id, additional_parms, control=None): """verifies id the value passed in is valid for the enum or object passed in. for example, if we want to see if a valid user is given, this will try to instantiate the User class with the given parameter @@ -937,13 +987,14 @@ def check_valid_field_values(self, val, enum_id, additional_parms, enum_id(val, **additional_parms) except Exception: raise PyleroLibException( - "{0} is not a valid value for {1}" - .format(val, enum_id.__name__)) + "{0} is not a valid value for {1}".format(val, enum_id.__name__) + ) else: valid_values = self.get_valid_field_values(enum_id, control) if val not in valid_values: - raise PyleroLibException("Acceptable values for {0} are:" - "{1}".format(enum_id, valid_values)) + raise PyleroLibException( + "Acceptable values for {0} are:" "{1}".format(enum_id, valid_values) + ) def get_valid_field_values(self, enum_id, control=None): """Gets the available enumeration options. @@ -966,8 +1017,9 @@ def get_valid_field_values(self, enum_id, control=None): if enum_base: enums = enum_base.get(control) if not enums: - enums = self.session.tracker_client.service. \ - getEnumOptionsForIdWithControl(project_id, enum_id, control) + enums = self.session.tracker_client.service.getEnumOptionsForIdWithControl( + project_id, enum_id, control + ) self._cache["enums"][enum_id] = {} self._cache["enums"][enum_id][control] = enums # the _cache contains _suds_object, so the id attribute is used. diff --git a/src/pylero/baseline.py b/src/pylero/baseline.py index 55244a1..93152e5 100644 --- a/src/pylero/baseline.py +++ b/src/pylero/baseline.py @@ -18,20 +18,18 @@ class Baseline(BasePolarion): description (string) baseline_id (string) name (string) - project (Project) -""" - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "base_revision": "baseRevision", - "description": "description", - "baseline_id": "id", - "name": "name", - "project": - {"field_name": "project", - "cls": Project}, - "uri": "_uri", - "_unresolved": "_unresolved"} + project (Project)""" + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "base_revision": "baseRevision", + "description": "description", + "baseline_id": "id", + "name": "name", + "project": {"field_name": "project", "cls": Project}, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:Baseline" @@ -53,7 +51,8 @@ def create(cls, project_id, name, description, revision): Tracker.createBaseline """ suds_object = cls.session.tracker_client.service.createBaseline( - project_id, name, description, revision) + project_id, name, description, revision + ) return cls(suds_object=suds_object) @classmethod @@ -71,7 +70,6 @@ def query(cls, query, sort="baseline_id"): Tracker.queryBaselines """ baselines = [] - for suds_base in cls.session.tracker_client.service.queryBaselines( - query, sort): + for suds_base in cls.session.tracker_client.service.queryBaselines(query, sort): baselines.append(Baseline(suds_object=suds_base)) return baselines diff --git a/src/pylero/build.py b/src/pylero/build.py index 7b79bc2..e02480a 100644 --- a/src/pylero/build.py +++ b/src/pylero/build.py @@ -30,35 +30,36 @@ class Build(BasePolarion): linked_work_items (ArrayOfBuildLinkedWorkItem) local_deployment_space_name (string) log_files (ArrayOfLocation) - start_time (dateTime) -""" - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "bir_location": "birLocation", - "build_descriptor_name": "buildDescriptorName", - "build_stamp": "buildStamp", - "build_status": "buildStatus", - "build_tag": "buildTag", - "build_test_results": - {"field_name": "buildTestResults", - "cls": BuildTestResults}, - "calculation_descriptor_name": - "calculationDescriptorName", - "creation_time": "creationTime", - "finish_time": "finishTime", - "build_id": "id", - "job_id": "jobId", - "linked_work_items": - {"field_name": "linkedWorkItems", - "is_array": True, - "cls": BuildLinkedWorkItem, - "arr_cls": ArrayOfBuildLinkedWorkItem, - "inner_field_name": "BuildLinkedWorkItem"}, - "local_deployment_space_name": "localDeploymentSpaceName", - "log_files": "logFiles", - "start_time": "startTime", - "uri": "_uri", - "_unresolved": "_unresolved"} + start_time (dateTime)""" + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "bir_location": "birLocation", + "build_descriptor_name": "buildDescriptorName", + "build_stamp": "buildStamp", + "build_status": "buildStatus", + "build_tag": "buildTag", + "build_test_results": { + "field_name": "buildTestResults", + "cls": BuildTestResults, + }, + "calculation_descriptor_name": "calculationDescriptorName", + "creation_time": "creationTime", + "finish_time": "finishTime", + "build_id": "id", + "job_id": "jobId", + "linked_work_items": { + "field_name": "linkedWorkItems", + "is_array": True, + "cls": BuildLinkedWorkItem, + "arr_cls": ArrayOfBuildLinkedWorkItem, + "inner_field_name": "BuildLinkedWorkItem", + }, + "local_deployment_space_name": "localDeploymentSpaceName", + "log_files": "logFiles", + "start_time": "startTime", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns2:Build" diff --git a/src/pylero/build_linked_work_item.py b/src/pylero/build_linked_work_item.py index 6f24a7c..5bcee81 100644 --- a/src/pylero/build_linked_work_item.py +++ b/src/pylero/build_linked_work_item.py @@ -15,18 +15,19 @@ class BuildLinkedWorkItem(BasePolarion): Attributes: revision (string) role (EnumOptionId) - work_item (WorkItem) -""" - _cls_suds_map = {"revision": "revision", - "role": - {"field_name": "role", - "cls": EnumOptionId, - "enum_id": "workitem-link-role"}, - "work_item": - {"field_name": "workItem", - "cls": _WorkItem}, - "uri": "_uri", - "_unresolved": "_unresolved"} + work_item (WorkItem)""" + + _cls_suds_map = { + "revision": "revision", + "role": { + "field_name": "role", + "cls": EnumOptionId, + "enum_id": "workitem-link-role", + }, + "work_item": {"field_name": "workItem", "cls": _WorkItem}, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns2:BuildLinkedWorkItem" diff --git a/src/pylero/build_test_results.py b/src/pylero/build_test_results.py index fd4ddae..53cbd38 100644 --- a/src/pylero/build_test_results.py +++ b/src/pylero/build_test_results.py @@ -14,13 +14,15 @@ class BuildTestResults(BasePolarion): error_count (int) failure_count (int) skipped_count (int) - test_count (int) -""" - _cls_suds_map = {"error_count": "errorCount", - "failure_count": "failureCount", - "skipped_count": "skippedCount", - "test_count": "testCount", - "uri": "_uri", - "_unresolved": "_unresolved"} + test_count (int)""" + + _cls_suds_map = { + "error_count": "errorCount", + "failure_count": "failureCount", + "skipped_count": "skippedCount", + "test_count": "testCount", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns2:BuildTestResults" diff --git a/src/pylero/category.py b/src/pylero/category.py index d73e59d..754925a 100644 --- a/src/pylero/category.py +++ b/src/pylero/category.py @@ -14,15 +14,15 @@ class Category(BasePolarion): Attributes: description (Text) category_id (string) - name (string) -""" - _cls_suds_map = {"description": - {"field_name": "description", - "cls": Text}, - "category_id": "id", - "name": "name", - "uri": "_uri", - "_unresolved": "_unresolved"} + name (string)""" + + _cls_suds_map = { + "description": {"field_name": "description", "cls": Text}, + "category_id": "id", + "name": "name", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:Category" _id_field = "category_id" diff --git a/src/pylero/change.py b/src/pylero/change.py index 791464b..b883902 100644 --- a/src/pylero/change.py +++ b/src/pylero/change.py @@ -19,14 +19,17 @@ class Change(BasePolarion): revision (string) user (string) """ - _cls_suds_map = {"creation": "creation", - "date": "date", - "diffs": "diffs", - "empty": "empty", - "invalid": "invalid", - "revision": "revision", - "user": "user", - "uri": "_uri", - "_unresolved": "_unresolved"} + + _cls_suds_map = { + "creation": "creation", + "date": "date", + "diffs": "diffs", + "empty": "empty", + "invalid": "invalid", + "revision": "revision", + "user": "user", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:Change" diff --git a/src/pylero/cli/cmd.py b/src/pylero/cli/cmd.py index d3f8290..1f515eb 100644 --- a/src/pylero/cli/cmd.py +++ b/src/pylero/cli/cmd.py @@ -14,73 +14,76 @@ class CmdList(object): - ''' An object to manage the command of list''' - - def list_documents_by_query(self, - query): - fields = ['document_id', - 'document_name', - 'author', - 'created', - 'updated', - 'updated_by'] + """An object to manage the command of list""" + + def list_documents_by_query(self, query): + fields = [ + "document_id", + "document_name", + "author", + "created", + "updated", + "updated_by", + ] doc_list = Document.query(query, False, fields) return doc_list def print_documents(self, docs): - print('Created%7sAuthor%7sDocument' % ('', '')) - print('-------%7s------%7s--------' % ('', '')) + print("Created%7sAuthor%7sDocument" % ("", "")) + print("-------%7s------%7s--------" % ("", "")) for doc in docs: - print('%-14s %-11s %s' % (doc.created.strftime('%Y-%m-%d'), - doc.author, - doc.document_id)) + print( + "%-14s %-11s %s" + % (doc.created.strftime("%Y-%m-%d"), doc.author, doc.document_id) + ) def list_workitems_in_doc(self, doc_name_with_space): - if doc_name_with_space.find('/') < 0: + if doc_name_with_space.find("/") < 0: print("Document format should be: 'space/document'") exit(1) doc = Document(Document.default_project, doc_name_with_space) - fields = ['work_item_id', - 'author', - 'title', - 'type', - 'status', - 'assignee', - 'categories', - 'comments', - 'created', - 'approvals', - 'updated'] + fields = [ + "work_item_id", + "author", + "title", + "type", + "status", + "assignee", + "categories", + "comments", + "created", + "approvals", + "updated", + ] self.workitem_list = doc.get_work_items(None, True, fields) return self.workitem_list def print_workitems(self, workitems): number = len(workitems) - print('\nTotal workitems: %d' % number) - print('Created%7sType%10sID%12sTitle' % ('', '', '')) - print('---------%5s-------%7s-----%9s--------' % ('', '', '')) + print("\nTotal workitems: %d" % number) + print("Created%7sType%10sID%12sTitle" % ("", "", "")) + print("---------%5s-------%7s-----%9s--------" % ("", "", "")) for wi in workitems: - created = str(wi.created).split(' ')[0] - print('%-13s %-13s %-13s %s' % (created, wi.type, - wi.work_item_id, wi.title)) + created = str(wi.created).split(" ")[0] + print( + "%-13s %-13s %-13s %s" % (created, wi.type, wi.work_item_id, wi.title) + ) def list_workitems_by_query(self, query, wi_type): - fields = ['work_item_id', - 'title', - 'author', - 'created'] + fields = ["work_item_id", "title", "author", "created"] if wi_type in ["testcase", "TestCase"]: workitem_list = TestCase.query(query, fields) elif wi_type in ["requirement", "Requirement"]: workitem_list = Requirement.query(query, fields) - elif wi_type == '': - workitem_list = TestCase.query(query, fields) + \ - Requirement.query(query, fields) + elif wi_type == "": + workitem_list = TestCase.query(query, fields) + Requirement.query( + query, fields + ) else: print("'%s' is invalid. Use testcase or requirement" % wi_type) exit(0) @@ -94,160 +97,147 @@ def print_steps_for_testcase(self, case_id): for step in steps.steps: stp = step.values[0].content exp = step.values[1].content - print('TestStep = %s' % stp) - print('ExpectedResult = %s\n' % exp) + print("TestStep = %s" % stp) + print("ExpectedResult = %s\n" % exp) if steps.steps is None: - print('No step for this tesecase!') + print("No step for this tesecase!") def print_links_for_requirement(self, req_id): req = Requirement(Requirement.default_project, req_id) - print('ID%-12sRole' % ('')) - print('-------%7s------' % ('')) + print("ID%-12sRole" % ("")) + print("-------%7s------" % ("")) for linked in req.linked_work_items_derived: - print('%-13s %-13s' % (linked.work_item_id, - linked.role)) + print("%-13s %-13s" % (linked.work_item_id, linked.role)) def print_links_for_testcase(self, case_id): tc = TestCase(TestCase.default_project, case_id) - print('ID%-12sRole' % ('')) - print('-------%7s------' % ('')) + print("ID%-12sRole" % ("")) + print("-------%7s------" % ("")) for linked in tc.linked_work_items: - print('%-13s %-13s' % (linked.work_item_id, - linked.role)) + print("%-13s %-13s" % (linked.work_item_id, linked.role)) def print_runs_by_query(self, query, is_template=False): - query_ful = 'project.id:%s AND %s' % (TestRun.default_project, query) - fields = ['query', - 'created', - 'test_run_id', - 'select_test_cases_by', - 'status', - 'plannedin', - 'assignee', - 'author'] - - st = TestRun.search(query_ful, - fields, - 'created', - -1, - is_template) - Object = '' + query_ful = "project.id:%s AND %s" % (TestRun.default_project, query) + fields = [ + "query", + "created", + "test_run_id", + "select_test_cases_by", + "status", + "plannedin", + "assignee", + "author", + ] + + st = TestRun.search(query_ful, fields, "created", -1, is_template) + Object = "" if is_template: - Object = 'Template' + Object = "Template" - prestr = 'Created Time %8sAuthor %3sAssignee' % ('', '') - latstr = '%sStatus %3sPlanID%10s%s' % ('', '', '', Object) - preln = '------------%9s------%4s------' % ('', '') - latln = '%2s--------%2s-------%9s--------' % ('', '', '') + prestr = "Created Time %8sAuthor %3sAssignee" % ("", "") + latstr = "%sStatus %3sPlanID%10s%s" % ("", "", "", Object) + preln = "------------%9s------%4s------" % ("", "") + latln = "%2s--------%2s-------%9s--------" % ("", "", "") - print('%s %s' % (prestr, latstr)) - print('%s %s' % (preln, latln)) + print("%s %s" % (prestr, latstr)) + print("%s %s" % (preln, latln)) for tp in st: - created_time = str(tp.created).split('.')[0] - print('%-20s %-9s %-8s %-10s%-15s %s' % (created_time, - tp.author, - tp.assignee, - tp.status, - tp.plannedin, - tp.test_run_id)) + created_time = str(tp.created).split(".")[0] + print( + "%-20s %-9s %-8s %-10s%-15s %s" + % ( + created_time, + tp.author, + tp.assignee, + tp.status, + tp.plannedin, + tp.test_run_id, + ) + ) def print_templates_by_query(self, query): self.print_runs_by_query(query, True) def print_testcases_from_run(self, run): tr = TestRun(run, None, TestRun.default_project) - print('(Only CaseID can be displayed when --run=$template)') - print('List cases for: %s\n' % run) - ttstr = ('Created Time %8sStatus %1sExecutedBy %2sCaseID' % ('', - '', - '')) - lnstr = ('------------%9s------%2s----------%3s------' % ('', '', '')) + print("(Only CaseID can be displayed when --run=$template)") + print("List cases for: %s\n" % run) + ttstr = "Created Time %8sStatus %1sExecutedBy %2sCaseID" % ("", "", "") + lnstr = "------------%9s------%2s----------%3s------" % ("", "", "") print(ttstr) print(lnstr) for rec in tr.records: - time = str(rec.executed).split('.')[0] - print('%-21s%-9s%-12s%-10s' % (time, - rec.result, - rec.executed_by, - rec.test_case_id)) + time = str(rec.executed).split(".")[0] + print( + "%-21s%-9s%-12s%-10s" + % (time, rec.result, rec.executed_by, rec.test_case_id) + ) def print_plan_ids(self, query): - pls = Plan.search(query, - sort='due_date', - limit=-1, - fields=['due_date', - 'name', - 'plan_id']) - - ttstr = ('Due Date%-5sPlan ID%-24sPlan Name' % ('', '')) - lnstr = ('----------- ---------- %-20s---------' % '') + pls = Plan.search( + query, sort="due_date", limit=-1, fields=["due_date", "name", "plan_id"] + ) + + ttstr = "Due Date%-5sPlan ID%-24sPlan Name" % ("", "") + lnstr = "----------- ---------- %-20s---------" % "" print(ttstr) print(lnstr) for pl in pls: - print('%-12s %-30s %s' % (pl.due_date, pl.plan_id, pl.name)) + print("%-12s %-30s %s" % (pl.due_date, pl.plan_id, pl.name)) class CmdUpdate(object): - ''' An object to manage the command of update''' + """An object to manage the command of update""" def update_all_case_results_for_run(self, run, result, user, comment): run = run.strip() tr = TestRun(run, None, TestRun.default_project) - print('\nUpdate %s:' % run) + print("\nUpdate %s:" % run) if not comment: - comment = '' + comment = "" - print('Total records: %d' % len(tr.records)) - print('Updated Date Time Result CaseID') - print('------------------- ------ -----------') + print("Total records: %d" % len(tr.records)) + print("Updated Date Time Result CaseID") + print("------------------- ------ -----------") - if user == 'None': + if user == "None": user = TestRun.logged_in_user_id for rec in tr.records: rec.executed = datetime.datetime.now() rec.executed_by = user - executed_str = str(rec.executed).split('.')[0] + executed_str = str(rec.executed).split(".")[0] rec.result = result rec.comment = comment - print('%-20s %-7s %s' % (executed_str, - result, - rec.test_case_id)) - tr.update_test_record_by_object(rec.test_case_id, - rec) - print('Done!') + print("%-20s %-7s %s" % (executed_str, result, rec.test_case_id)) + tr.update_test_record_by_object(rec.test_case_id, rec) + print("Done!") def update_all_case_results_for_runs(self, runs, result, user, comment): - if runs.find(','): - for run in runs.split(','): - self.update_all_case_results_for_run(run, result, - user, comment) + if runs.find(","): + for run in runs.split(","): + self.update_all_case_results_for_run(run, result, user, comment) else: print("Please use comma ',' to seperate your runs!") - def update_1_case_result_for_run(self, - run, - testcase, - result, - user, - comment): + def update_1_case_result_for_run(self, run, testcase, result, user, comment): if not comment: - comment = '' + comment = "" tr = TestRun(run.strip(), None, TestRun.default_project) - print('Update %s:' % run) + print("Update %s:" % run) - if user == 'None': + if user == "None": user = TestRun.logged_in_user_id is_found = False @@ -260,23 +250,25 @@ def update_1_case_result_for_run(self, rec.comment = comment tr.update_test_record_by_object(testcase, rec) - print("%4sSet %s to %s (verdict comment: '%s')" % ('', - testcase, - result, - comment)) + print( + "%4sSet %s to %s (verdict comment: '%s')" + % ("", testcase, result, comment) + ) return 0 if not is_found: - print('Test case %s is not found in run.' % testcase) - - def update_document(self, - space, - doc_name, - doc_title, - wi_types=None, - doc_type=None, - structure_link_role="parent", - content=''): + print("Test case %s is not found in run." % testcase) + + def update_document( + self, + space, + doc_name, + doc_title, + wi_types=None, + doc_type=None, + structure_link_role="parent", + content="", + ): cl = CmdList() if cl.list_documents_by_query(doc_name): @@ -287,17 +279,19 @@ def update_document(self, # the content could be file or data if os.path.exists(content): file_path = content - with open(content, mode='r') as check_file: + with open(content, mode="r") as check_file: content = check_file.read() - doc = Document.create(Document.default_project, - space, - doc_name, - doc_title, - wi_types, - doc_type, - structure_link_role, - content) + doc = Document.create( + Document.default_project, + space, + doc_name, + doc_title, + wi_types, + doc_type, + structure_link_role, + content, + ) if cl.list_documents_by_query(doc_name): print("Created document '%s/%s'" % (space, doc_name)) @@ -314,90 +308,86 @@ def update_document(self, print("Failed to create document '%s/%s'" % (space, doc_name)) return False - def update_run(self, - run, - template=None, - plannedin=None, - assignee=None, - status=None, - description=None, - is_template=False): + def update_run( + self, + run, + template=None, + plannedin=None, + assignee=None, + status=None, + description=None, + is_template=False, + ): run = run.strip() - query_ful = 'project.id:%s AND id:\"%s\"' % (TestRun.default_project, - run) - - fields = ['query', - 'created', - 'test_run_id', - 'select_test_cases_by', - 'status', - 'plannedin', - 'assignee', - 'author'] - st = TestRun.search(query_ful, - fields, - 'created', - -1, - is_template) + query_ful = 'project.id:%s AND id:"%s"' % (TestRun.default_project, run) + + fields = [ + "query", + "created", + "test_run_id", + "select_test_cases_by", + "status", + "plannedin", + "assignee", + "author", + ] + st = TestRun.search(query_ful, fields, "created", -1, is_template) # Update run if exists, otherwise create it. if st: - print('Update the existing run: %s' % run) - tr = TestRun(run, - None, - TestRun.default_project) + print("Update the existing run: %s" % run) + tr = TestRun(run, None, TestRun.default_project) # set fields - if assignee != 'None': + if assignee != "None": tr.assignee = assignee - print('%4sSet Assignee to %s' % ('', assignee)) + print("%4sSet Assignee to %s" % ("", assignee)) if plannedin is not None: tr.plannedin = plannedin - print('%4sSet Plannedin to %s' % ('', plannedin)) + print("%4sSet Plannedin to %s" % ("", plannedin)) if status is not None: tr.status = status - print('%4sSet Status to %s' % ('', status)) + print("%4sSet Status to %s" % ("", status)) if description is not None: tr.description = description - print('%4sSet Description to %s' % ('', description)) + print("%4sSet Description to %s" % ("", description)) tr.update() else: - tr = TestRun.create(TestRun.default_project, - run, - template, - assignee=assignee, - plannedin=plannedin, - status=status, - description=description) + tr = TestRun.create( + TestRun.default_project, + run, + template, + assignee=assignee, + plannedin=plannedin, + status=status, + description=description, + ) # display fields - if assignee != 'None': - print('%4sSet Assignee to %s' % ('', assignee)) + if assignee != "None": + print("%4sSet Assignee to %s" % ("", assignee)) if plannedin is not None: - print('%4sSet Plannedin to %s' % ('', plannedin)) + print("%4sSet Plannedin to %s" % ("", plannedin)) if status is not None: - print('%4sSet Status to %s' % ('', status)) + print("%4sSet Status to %s" % ("", status)) if description is not None: - print('%4sSet Description to %s' % ('', description)) - print('Created %s:' % run) - - def update_runs(self, - runs, - template=None, - plannedin=None, - assignee=None, - status=None, - description=None): - - if runs.find(','): - for run in runs.split(','): - self.update_run(run, - template, - plannedin, - assignee, - status, - description) - print('Done!') + print("%4sSet Description to %s" % ("", description)) + print("Created %s:" % run) + + def update_runs( + self, + runs, + template=None, + plannedin=None, + assignee=None, + status=None, + description=None, + ): + + if runs.find(","): + for run in runs.split(","): + self.update_run(run, template, plannedin, assignee, status, description) + print("Done!") else: print("Please use comma ',' to seperate your runs!") diff --git a/src/pylero/comment.py b/src/pylero/comment.py index 5c5633b..1b008a6 100644 --- a/src/pylero/comment.py +++ b/src/pylero/comment.py @@ -30,37 +30,34 @@ class Comment(BasePolarion): title (string) visible_to (ArrayOfstring) """ - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "child_comment_uris": - {"field_name": "childCommentURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "created": "created", - "comment_id": "id", - "parent_comment_uri": - {"field_name": "parentCommentURI", - "cls": SubterraURI}, - "resolved": "resolved", - "signature_data": - {"field_name": "signatureData", - "cls": SignatureData}, - "tags": - {"field_name": "tags", - "is_array": True, - "cls": EnumOptionId, - "arr_cls": ArrayOfEnumOptionId, - "inner_field_name": "EnumOptionId"}, - "text": - {"field_name": "text", - "cls": Text}, - "title": "title", - "visible_to": "visibleTo", - "uri": "_uri", - "_unresolved": "_unresolved"} + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "child_comment_uris": { + "field_name": "childCommentURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "created": "created", + "comment_id": "id", + "parent_comment_uri": {"field_name": "parentCommentURI", "cls": SubterraURI}, + "resolved": "resolved", + "signature_data": {"field_name": "signatureData", "cls": SignatureData}, + "tags": { + "field_name": "tags", + "is_array": True, + "cls": EnumOptionId, + "arr_cls": ArrayOfEnumOptionId, + "inner_field_name": "EnumOptionId", + }, + "text": {"field_name": "text", "cls": Text}, + "title": "title", + "visible_to": "visibleTo", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:Comment" diff --git a/src/pylero/custom.py b/src/pylero/custom.py index 0d4236e..41ab1ea 100644 --- a/src/pylero/custom.py +++ b/src/pylero/custom.py @@ -13,13 +13,12 @@ class Custom(BasePolarion): Attributes: key (string) - value (EnumOptionId) -""" - _cls_suds_map = {"key": "key", - "value": - {"field_name": "value", - "cls": EnumOptionId} - } + value (EnumOptionId)""" + + _cls_suds_map = { + "key": "key", + "value": {"field_name": "value", "cls": EnumOptionId}, + } _obj_client = "test_management_client" _obj_struct = "tns4:Custom" diff --git a/src/pylero/custom_field.py b/src/pylero/custom_field.py index 5ceb87b..8cd9d28 100644 --- a/src/pylero/custom_field.py +++ b/src/pylero/custom_field.py @@ -13,10 +13,8 @@ class CustomField(BasePolarion): Attributes: key (string) parent_item_uri (string) - value (anyType) -""" - _cls_suds_map = {"key": "key", - "parent_item_uri": "parentItemURI", - "value": "value"} + value (anyType)""" + + _cls_suds_map = {"key": "key", "parent_item_uri": "parentItemURI", "value": "value"} _obj_client = "tracker_client" _obj_struct = "tns3:CustomField" diff --git a/src/pylero/custom_field_type.py b/src/pylero/custom_field_type.py index c3b6102..dba1b75 100644 --- a/src/pylero/custom_field_type.py +++ b/src/pylero/custom_field_type.py @@ -19,18 +19,21 @@ class CustomFieldType(BasePolarion): required (boolean) type (string) """ -# id field is called cft_id and not custom_field_type_id because it is often -# mixed with enum_custom_field_type and they need to be accessed -# interchangeably - _cls_suds_map = {"default_value": "defaultValue", - "depends_on": "dependsOn", - "description": "description", - "cft_id": "id", - "name": "name", - "multi": "multi", - "required": "required", - "type": "type", - "uri": "_uri", - "_unresolved": "_unresolved"} + + # id field is called cft_id and not custom_field_type_id because it is often + # mixed with enum_custom_field_type and they need to be accessed + # interchangeably + _cls_suds_map = { + "default_value": "defaultValue", + "depends_on": "dependsOn", + "description": "description", + "cft_id": "id", + "name": "name", + "multi": "multi", + "required": "required", + "type": "type", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:CustomFieldType" diff --git a/src/pylero/document.py b/src/pylero/document.py index 86a0715..7ae6da5 100644 --- a/src/pylero/document.py +++ b/src/pylero/document.py @@ -55,99 +55,100 @@ class Document(BasePolarion): type (EnumOptionId) updated (dateTime) updated_by (User) - uses_outline_numbering (boolean) -""" + uses_outline_numbering (boolean)""" _cls_suds_map = { - "allowed_wi_types": - {"field_name": "allowedWITypes", - "is_array": True, - "cls": EnumOptionId, - "arr_cls": ArrayOfEnumOptionId, - "inner_field_name": "EnumOptionId", - "enum_id": "workitem-type"}, - "are_links_from_parent_to_child": - "areLinksFromParentToChild", - "author": - {"field_name": "author", - "cls": User}, + "allowed_wi_types": { + "field_name": "allowedWITypes", + "is_array": True, + "cls": EnumOptionId, + "arr_cls": ArrayOfEnumOptionId, + "inner_field_name": "EnumOptionId", + "enum_id": "workitem-type", + }, + "are_links_from_parent_to_child": "areLinksFromParentToChild", + "author": {"field_name": "author", "cls": User}, "auto_suspect": "autoSuspect", - "branched_from": - {"field_name": "branchedFrom"}, # populated in circ refs + "branched_from": {"field_name": "branchedFrom"}, # populated in circ refs "branched_with_query": "branchedWithQuery", - "comments": - {"field_name": "comments", - "is_array": True, - "cls": ModuleComment, - "arr_cls": ArrayOfModuleComment, - "inner_field_name": "ModuleComment"}, + "comments": { + "field_name": "comments", + "is_array": True, + "cls": ModuleComment, + "arr_cls": ArrayOfModuleComment, + "inner_field_name": "ModuleComment", + }, "created": "created", "derived_fields": "derived_fields", # arrayOfstring? - "derived_from_uri": - {"field_name": "derivedFromURI", - "cls": SubterraURI}, - "derived_from_link_role": - {"field_name": "derivedFromLinkRole", - "cls": EnumOptionId}, - "home_page_content": - {"field_name": "homePageContent", - "cls": Text}, + "derived_from_uri": {"field_name": "derivedFromURI", "cls": SubterraURI}, + "derived_from_link_role": { + "field_name": "derivedFromLinkRole", + "cls": EnumOptionId, + }, + "home_page_content": {"field_name": "homePageContent", "cls": Text}, "document_id": "id", "space": "moduleLocation", "document_absolute_location": "moduleAbsoluteLocation", "document_folder": "moduleFolder", "document_name": "moduleName", - "project_id": - {"field_name": "project", - "cls": Project}, - "signature_contexts": - {"field_name": "signatureContexts", - "is_array": True, - "cls": SignatureContext, - "arr_cls": ArrayOfSignatureContext, - "inner_field_name": "SignatureContext"}, - "status": - {"field_name": "status", - "cls": EnumOptionId, - "enum_id": "documents/document-status"}, - "structure_link_role": - {"field_name": "structureLinkRole", - "cls": EnumOptionId}, + "project_id": {"field_name": "project", "cls": Project}, + "signature_contexts": { + "field_name": "signatureContexts", + "is_array": True, + "cls": SignatureContext, + "arr_cls": ArrayOfSignatureContext, + "inner_field_name": "SignatureContext", + }, + "status": { + "field_name": "status", + "cls": EnumOptionId, + "enum_id": "documents/document-status", + }, + "structure_link_role": {"field_name": "structureLinkRole", "cls": EnumOptionId}, "title": "title", - "type": - {"field_name": "type", - "cls": EnumOptionId, - "enum_id": "documents/document-type"}, + "type": { + "field_name": "type", + "cls": EnumOptionId, + "enum_id": "documents/document-type", + }, "updated": "updated", - "updated_by": - {"field_name": "updatedBy", - "cls": User}, + "updated_by": {"field_name": "updatedBy", "cls": User}, "uses_outline_numbering": "usesOutlineNumbering", - "custom_fields": - {"field_name": "customFields", - "is_array": True, - "cls": Custom, - "arr_cls": ArrayOfCustom, - "inner_field_name": "Custom"}, + "custom_fields": { + "field_name": "customFields", + "is_array": True, + "cls": Custom, + "arr_cls": ArrayOfCustom, + "inner_field_name": "Custom", + }, "uri": "_uri", - "_unresolvable": "_unresolvable"} + "_unresolvable": "_unresolvable", + } _obj_client = "test_management_client" _obj_struct = "tns4:Module" # The uri struct of a module is different then others because of extra # moduleFolder element. Also requires a substitution from # to / and back - URI_STRUCT = "subterra:data-service:objects:/default/" \ - "%(project)s${%(obj)s}{moduleFolder}%(id)s" + URI_STRUCT = ( + "subterra:data-service:objects:/default/" + "%(project)s${%(obj)s}{moduleFolder}%(id)s" + ) # must wrap lambda with classmethod so it can be used as such URI_ID_GET_REPLACE = classmethod(lambda cls, x: x.replace("#", "/")) URI_ID_SET_REPLACE = classmethod(lambda cls, x: x.replace("/", "#")) @classmethod @tx_wrapper - def create(cls, project_id, space, document_name, document_title, - allowed_wi_types, - document_type, - structure_link_role="parent", - home_page_content=""): + def create( + cls, + project_id, + space, + document_name, + document_title, + allowed_wi_types, + document_type, + structure_link_role="parent", + home_page_content="", + ): # There is no document object. # don't know what to do with the URI it returns. """class method create Creates a document or an old-style @@ -173,13 +174,18 @@ def create(cls, project_id, space, document_name, document_title, """ if isinstance(allowed_wi_types, basestring): allowed_wi_types = [allowed_wi_types] - awit = [EnumOptionId(item)._suds_object - for item in allowed_wi_types] + awit = [EnumOptionId(item)._suds_object for item in allowed_wi_types] slr = EnumOptionId(structure_link_role)._suds_object try: uri = cls.session.tracker_client.service.createDocument( - project_id, space, document_name, document_title, awit, - slr, home_page_content) + project_id, + space, + document_name, + document_title, + awit, + slr, + home_page_content, + ) doc = Document(uri=uri) doc.type = document_type # for some reason, when in a tx (@tx_wrapper), the @@ -200,8 +206,8 @@ def create(cls, project_id, space, document_name, document_title, except suds.WebFault as e: if "Invalid document on location Location" in e.fault.faultstring: raise PyleroLibException( - "Document {0}/{1} already exists".format(space, - document_name)) + "Document {0}/{1} already exists".format(space, document_name) + ) else: raise PyleroLibException(e.fault) @@ -231,15 +237,23 @@ def get_documents(cls, project_id, space, fields=[]): if p_fields: function_name += "WithFields" parms += [p_fields] - for suds_module in getattr(cls.session.tracker_client.service, - function_name)(*parms): + for suds_module in getattr(cls.session.tracker_client.service, function_name)( + *parms + ): docs.append(cls(suds_object=suds_module)) return docs @classmethod - def query(cls, query, is_sql=False, fields=["document_id"], - sort="document_id", limit=-1, baseline_revision=None, - query_uris=False): + def query( + cls, + query, + is_sql=False, + fields=["document_id"], + sort="document_id", + limit=-1, + baseline_revision=None, + query_uris=False, + ): """Searches for Modules/Documents. Args: @@ -302,8 +316,14 @@ def query(cls, query, is_sql=False, fields=["document_id"], lst_doc = [Document(suds_object=doc) for doc in docs] return lst_doc - def __init__(self, project_id=None, doc_with_space=None, fields=None, - uri=None, suds_object=None): + def __init__( + self, + project_id=None, + doc_with_space=None, + fields=None, + uri=None, + suds_object=None, + ): """constructor for the Module object. Gets the module object from the Polarion server based on parameters passed in. @@ -341,12 +361,13 @@ def __init__(self, project_id=None, doc_with_space=None, fields=None, if fields: function_name = "WithFields" parms.append(self._convert_obj_fields_to_polarion(fields)) - self._suds_object = getattr(self.session.tracker_client.service, - function_name)(*parms) + self._suds_object = getattr( + self.session.tracker_client.service, function_name + )(*parms) if getattr(self._suds_object, "_unresolvable", True): raise PyleroLibException( - "The Document {0} was not found.".format(doc_with_space or - uri)) + "The Document {0} was not found.".format(doc_with_space or uri) + ) def _fix_circular_refs(self): # a class can't reference itself as a class attribute. @@ -372,19 +393,20 @@ def create_work_item(self, parent_id, w_item): w_item.verify_required() suds_wi = w_item._suds_object else: - raise PyleroLibException( - "the w_item parameter must be a _WorkItem") + raise PyleroLibException("the w_item parameter must be a _WorkItem") if parent_id: - parent_uri = _WorkItem(work_item_id=parent_id, - project_id=self.project_id).uri + parent_uri = _WorkItem( + work_item_id=parent_id, project_id=self.project_id + ).uri else: doc_wis = self.get_work_items(None, False, None) if doc_wis: parent_uri = doc_wis[0].uri else: parent_uri = None - wi_uri = self.session.tracker_client.service. \ - createWorkItemInModule(self.uri, parent_uri, suds_wi) + wi_uri = self.session.tracker_client.service.createWorkItemInModule( + self.uri, parent_uri, suds_wi + ) new_wi = w_item.__class__(uri=wi_uri) new_wi._changed_fields = w_item._changed_fields new_wi.update() @@ -403,8 +425,9 @@ def delete(self): self._verify_obj() self.session.tracker_client.service.deleteModule(self.uri) - def get_work_items(self, parent_work_item_id, deep, - fields=["work_item_id", "type"]): + def get_work_items( + self, parent_work_item_id, deep, fields=["work_item_id", "type"] + ): """Returns work items (with given fields set) contained in given Module/Document under given parent (if specified). @@ -426,20 +449,23 @@ def get_work_items(self, parent_work_item_id, deep, """ self._verify_obj() if parent_work_item_id: - parent_uri = _WorkItem(work_item_id=parent_work_item_id, - project_id=self.project_id).uri + parent_uri = _WorkItem( + work_item_id=parent_work_item_id, project_id=self.project_id + ).uri else: parent_uri = None p_fields = _WorkItem._convert_obj_fields_to_polarion(fields) - suds_wi = self.session.tracker_client.service. \ - getModuleWorkItems(self.uri, parent_uri, deep, p_fields) + suds_wi = self.session.tracker_client.service.getModuleWorkItems( + self.uri, parent_uri, deep, p_fields + ) work_items = [] for w_item in suds_wi: work_items.append(_WorkItem(suds_object=w_item)) return work_items - def move_work_item_here(self, work_item_id, parent_id, position=-1, - retain_flow=True): + def move_work_item_here( + self, work_item_id, parent_id, position=-1, retain_flow=True + ): """Moves a work item to a specific position in a Document. If the work item is not yet inside the Document it will be moved into the Document. @@ -469,7 +495,8 @@ def move_work_item_here(self, work_item_id, parent_id, position=-1, else: parent_uri = None self.session.tracker_client.service.moveWorkItemToDocument( - wi.uri, self.uri, parent_uri, position, retain_flow) + wi.uri, self.uri, parent_uri, position, retain_flow + ) def add_referenced_work_item(self, work_item_id): """Adds a work item to the document as a referenced work_item to the @@ -485,8 +512,10 @@ def add_referenced_work_item(self, work_item_id): self._verify_obj() # verify that the work item passed in exists _WorkItem(project_id=self.project_id, work_item_id=work_item_id) - ref_wi_template = """
""" + ) self.home_page_content += ref_wi_template % work_item_id self.update() diff --git a/src/pylero/enum_custom_field_type.py b/src/pylero/enum_custom_field_type.py index 8659822..495fcfb 100644 --- a/src/pylero/enum_custom_field_type.py +++ b/src/pylero/enum_custom_field_type.py @@ -18,21 +18,23 @@ class EnumCustomFieldType(BasePolarion): id (string) name (string) required (boolean) - type (string) -""" -# id field is called cft_id and not enum_custom_field_type_id because it is -# often mixed with custom_field_type and they need to be accessed -# interchangeably - _cls_suds_map = {"default_value": "defaultValue", - "depends_on": "dependsOn", - "description": "description", - "enum_id": "enumId", - "cft_id": "id", - "name": "name", - "multi": "multi", - "required": "required", - "type": "type", - "uri": "_uri", - "_unresolved": "_unresolved"} + type (string)""" + + # id field is called cft_id and not enum_custom_field_type_id because it is + # often mixed with custom_field_type and they need to be accessed + # interchangeably + _cls_suds_map = { + "default_value": "defaultValue", + "depends_on": "dependsOn", + "description": "description", + "enum_id": "enumId", + "cft_id": "id", + "name": "name", + "multi": "multi", + "required": "required", + "type": "type", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:EnumCustomFieldType" diff --git a/src/pylero/enum_option.py b/src/pylero/enum_option.py index 24b3564..f48795f 100644 --- a/src/pylero/enum_option.py +++ b/src/pylero/enum_option.py @@ -19,19 +19,19 @@ class EnumOption(BasePolarion): name (string) phantom (boolean) properties (Properties) - sequence_number (int) -""" - _cls_suds_map = {"default": "default", - "enum_id": "enumId", - "hidden": "hidden", - "enum_option_id": "id", - "name": "name", - "phantom": "phantom", - "properties": - {"field_name": "properties", - "cls": Properties}, - "sequence_number": "sequenceNumber", - "uri": "_uri", - "_unresolved": "_unresolved"} + sequence_number (int)""" + + _cls_suds_map = { + "default": "default", + "enum_id": "enumId", + "hidden": "hidden", + "enum_option_id": "id", + "name": "name", + "phantom": "phantom", + "properties": {"field_name": "properties", "cls": Properties}, + "sequence_number": "sequenceNumber", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:EnumOption" diff --git a/src/pylero/enum_option_id.py b/src/pylero/enum_option_id.py index f6be0aa..572b11b 100644 --- a/src/pylero/enum_option_id.py +++ b/src/pylero/enum_option_id.py @@ -9,6 +9,7 @@ class EnumOptionId(BasePolarion): """An object to manage Polarion TestManagement tns4:EnumOptionId""" + _cls_suds_map = {"enum_id": "id"} _id_field = "enum_id" _obj_client = "test_management_client" @@ -20,6 +21,7 @@ def __init__(self, enum_id=None, suds_object=None): class ArrayOfEnumOptionId(BasePolarion): """An object to manage Polarion TestManagement tns4:ArrayOfEnumOptionId""" + _obj_client = "test_management_client" _obj_struct = "tns4:ArrayOfEnumOptionId" _cls_inner = EnumOptionId diff --git a/src/pylero/externally_linked_work_item.py b/src/pylero/externally_linked_work_item.py index 1c25b5c..30b418a 100644 --- a/src/pylero/externally_linked_work_item.py +++ b/src/pylero/externally_linked_work_item.py @@ -13,17 +13,19 @@ class ExternallyLinkedWorkItem(BasePolarion): Attributes: role (EnumOptionId) - work_item_uri (string) -""" + work_item_uri (string)""" + _cls_suds_map = { - "role": - {"field_name": "role", - "cls": EnumOptionId, - "enum_id": "workitem-link-role"}, - "work_item_id": # cls is added in _fix_circular_refs function - {"field_name": "workItemURI", - "named_arg": "uri", - "sync_field": "uri"} + "role": { + "field_name": "role", + "cls": EnumOptionId, + "enum_id": "workitem-link-role", + }, + "work_item_id": { # cls is added in _fix_circular_refs function + "field_name": "workItemURI", + "named_arg": "uri", + "sync_field": "uri", + }, } _obj_client = "builder_client" _obj_struct = "tns5:ExternallyLinkedWorkItem" @@ -38,9 +40,11 @@ def _fix_circular_refs(self): # need to pass in the project_id parm to the Work Item, # but it is not given before instantiation from pylero.work_item import _WorkItem + self._cls_suds_map["work_item_id"]["cls"] = _WorkItem - self._cls_suds_map["work_item_id"]["additional_parms"] = \ - {"project_id": self.project_id} + self._cls_suds_map["work_item_id"]["additional_parms"] = { + "project_id": self.project_id + } class ArrayOfExternallyLinkedWorkItem(BasePolarion): diff --git a/src/pylero/field_diff.py b/src/pylero/field_diff.py index b6bd296..5a728c6 100644 --- a/src/pylero/field_diff.py +++ b/src/pylero/field_diff.py @@ -16,15 +16,17 @@ class FieldDiff(BasePolarion): before (anyType) collection (boolean) field_name (string) - removed (ArrayOf_xsd_anyType) -""" - _cls_suds_map = {"added": "added", - "after": "after", - "before": "before", - "collection": "collection", - "field_name": "fieldName", - "removed": "removed", - "uri": "_uri", - "_unresolved": "_unresolved"} + removed (ArrayOf_xsd_anyType)""" + + _cls_suds_map = { + "added": "added", + "after": "after", + "before": "before", + "collection": "collection", + "field_name": "fieldName", + "removed": "removed", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:FieldDiff" diff --git a/src/pylero/hyperlink.py b/src/pylero/hyperlink.py index 8900e01..73dcacf 100644 --- a/src/pylero/hyperlink.py +++ b/src/pylero/hyperlink.py @@ -13,13 +13,16 @@ class Hyperlink(BasePolarion): Attributes: role (EnumOptionId) - uri (string) -""" + uri (string)""" + _cls_suds_map = { - "role": {"field_name": "role", - "cls": EnumOptionId, - "enum_id": "hyperlink-role"}, - "uri": "uri"} + "role": { + "field_name": "role", + "cls": EnumOptionId, + "enum_id": "hyperlink-role", + }, + "uri": "uri", + } _obj_client = "builder_client" _obj_struct = "tns5:Hyperlink" diff --git a/src/pylero/imported_comment.py b/src/pylero/imported_comment.py index f81b60a..170344d 100644 --- a/src/pylero/imported_comment.py +++ b/src/pylero/imported_comment.py @@ -13,12 +13,14 @@ class ImportedComment(BasePolarion): Attributes: author (string) created (dateTime) - initials (string) -""" - _cls_suds_map = {"author": "author", - "created": "created", - "initials": "initials", - "uri": "_uri", - "_unresolved": "_unresolved"} + initials (string)""" + + _cls_suds_map = { + "author": "author", + "created": "created", + "initials": "initials", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "test_management_client" _obj_struct = "tns4:ImportedComment" diff --git a/src/pylero/language_definition.py b/src/pylero/language_definition.py index ee867b6..485a97f 100644 --- a/src/pylero/language_definition.py +++ b/src/pylero/language_definition.py @@ -12,11 +12,13 @@ class LanguageDefinition(BasePolarion): Attributes: language_definition_id (string) - label (string) -""" - _cls_suds_map = {"language_definition_id": "id", - "label": "label", - "uri": "_uri", - "_unresolved": "_unresolved"} + label (string)""" + + _cls_suds_map = { + "language_definition_id": "id", + "label": "label", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:LanguageDefinition" diff --git a/src/pylero/license_info.py b/src/pylero/license_info.py index 214df5a..b750031 100644 --- a/src/pylero/license_info.py +++ b/src/pylero/license_info.py @@ -12,11 +12,13 @@ class LicenseInfo(BasePolarion): Attributes: license (string) - slots (int) -""" - _cls_suds_map = {"license": "license", - "slots": "slots", - "uri": "_uri", - "_unresolved": "_unresolved"} + slots (int)""" + + _cls_suds_map = { + "license": "license", + "slots": "slots", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "security_client" _obj_struct = "tns3:LicenseInfo" diff --git a/src/pylero/linked_work_item.py b/src/pylero/linked_work_item.py index 6733724..3b41aeb 100644 --- a/src/pylero/linked_work_item.py +++ b/src/pylero/linked_work_item.py @@ -15,19 +15,21 @@ class LinkedWorkItem(BasePolarion): revision (string) role (EnumOptionId) suspect (boolean) - work_item_id (string) -""" + work_item_id (string)""" + _cls_suds_map = { "revision": "revision", - "role": - {"field_name": "role", - "cls": EnumOptionId, - "enum_id": "workitem-link-role"}, + "role": { + "field_name": "role", + "cls": EnumOptionId, + "enum_id": "workitem-link-role", + }, "suspect": "suspect", - "work_item_id": # class added in _fix_circular_refs function - {"field_name": "workItemURI", - "named_arg": "uri", - "sync_field": "uri"} + "work_item_id": { # class added in _fix_circular_refs function + "field_name": "workItemURI", + "named_arg": "uri", + "sync_field": "uri", + }, } _obj_client = "builder_client" _obj_struct = "tns5:LinkedWorkItem" @@ -42,9 +44,11 @@ def _fix_circular_refs(self): # need to pass in the project_id parm to the Work Item, # but it is not given before instantiation from pylero.work_item import _WorkItem + self._cls_suds_map["work_item_id"]["cls"] = _WorkItem - self._cls_suds_map["work_item_id"]["additional_parms"] = \ - {"project_id": self.project_id} + self._cls_suds_map["work_item_id"]["additional_parms"] = { + "project_id": self.project_id + } class ArrayOfLinkedWorkItem(BasePolarion): diff --git a/src/pylero/module_comment.py b/src/pylero/module_comment.py index 7a86b52..79a5b03 100644 --- a/src/pylero/module_comment.py +++ b/src/pylero/module_comment.py @@ -29,43 +29,38 @@ class ModuleComment(BasePolarion): resolved (boolean) signature_data (SignatureData) tags (ArrayOfEnumOptionId) - text (Text) -""" - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "child_comment_uris": - {"field_name": "childCommentURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "created": "created", - "module_comment_id": "id", - "imported_comment": - {"field_name": "importedComment", - "cls": ImportedComment}, - "parent_comment_uri": - {"field_name": "parentCommentURI", - "cls": SubterraURI}, - "referred_work_item_uri": - {"field_name": "referredWorkItemURI", - "cls": SubterraURI}, - "resolved": "resolved", - "signature_data": - {"field_name": "signatureData", - "cls": SignatureData}, - "tags": - {"field_name": "tags", - "is_array": True, - "cls": EnumOptionId, - "arr_cls": ArrayOfEnumOptionId, - "inner_field_name": "EnumOptionId"}, - "text": - {"field_name": "text", - "cls": Text}, - "uri": "_uri", - "_unresolved": "_unresolved"} + text (Text)""" + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "child_comment_uris": { + "field_name": "childCommentURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "created": "created", + "module_comment_id": "id", + "imported_comment": {"field_name": "importedComment", "cls": ImportedComment}, + "parent_comment_uri": {"field_name": "parentCommentURI", "cls": SubterraURI}, + "referred_work_item_uri": { + "field_name": "referredWorkItemURI", + "cls": SubterraURI, + }, + "resolved": "resolved", + "signature_data": {"field_name": "signatureData", "cls": SignatureData}, + "tags": { + "field_name": "tags", + "is_array": True, + "cls": EnumOptionId, + "arr_cls": ArrayOfEnumOptionId, + "inner_field_name": "EnumOptionId", + }, + "text": {"field_name": "text", "cls": Text}, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "test_management_client" _obj_struct = "tns4:ModuleComment" diff --git a/src/pylero/plan.py b/src/pylero/plan.py index f65524f..a99baa0 100644 --- a/src/pylero/plan.py +++ b/src/pylero/plan.py @@ -52,37 +52,36 @@ class Plan(BasePolarion): started_on (dateTime) status (EnumOptionId) template_uri (SubterraURI) - updated (dateTime) -""" + updated (dateTime)""" + _cls_suds_map = { - "allowed_types": - {"field_name": "allowedTypes", - "is_array": True, - "cls": EnumOptionId, - "arr_cls": ArrayOfEnumOptionId, - "inner_field_name": "EnumOptionId", - "enum_id": "workitem-type"}, - "author": - {"field_name": "authorURI", - "cls": User, - "named_arg": "uri", - "sync_field": "uri"}, - "calculation_type": - {"field_name": "calculationType", - "cls": EnumOptionId}, + "allowed_types": { + "field_name": "allowedTypes", + "is_array": True, + "cls": EnumOptionId, + "arr_cls": ArrayOfEnumOptionId, + "inner_field_name": "EnumOptionId", + "enum_id": "workitem-type", + }, + "author": { + "field_name": "authorURI", + "cls": User, + "named_arg": "uri", + "sync_field": "uri", + }, + "calculation_type": {"field_name": "calculationType", "cls": EnumOptionId}, "capacity": "capacity", "color": "color", "created": "created", - "custom_fields": - {"field_name": "customFields", - "is_array": True, - "cls": Custom, - "arr_cls": ArrayOfCustom, - "inner_field_name": "Custom"}, + "custom_fields": { + "field_name": "customFields", + "is_array": True, + "cls": Custom, + "arr_cls": ArrayOfCustom, + "inner_field_name": "Custom", + }, "default_estimate": "defaultEstimate", - "description": - {"field_name": "description", - "cls": Text}, + "description": {"field_name": "description", "cls": Text}, "due_date": "dueDate", "estimation_field": "estimationField", "finished_on": "finishedOn", @@ -99,29 +98,28 @@ class Plan(BasePolarion): "plan_id": "id", "previous_time_spent": "previousTimeSpent", "prioritization_field": "prioritizationField", - "project_id": - {"field_name": "projectURI", - "cls": Project, - "named_arg": "uri", - "sync_field": "uri"}, - "records": - {"field_name": "records", - "is_array": True, - "cls": PlanRecord, - "arr_cls": ArrayOfPlanRecord, - "inner_field_name": "PlanRecord"}, + "project_id": { + "field_name": "projectURI", + "cls": Project, + "named_arg": "uri", + "sync_field": "uri", + }, + "records": { + "field_name": "records", + "is_array": True, + "cls": PlanRecord, + "arr_cls": ArrayOfPlanRecord, + "inner_field_name": "PlanRecord", + }, "sort_order": "sortOrder", "start_date": "startDate", "started_on": "startedOn", - "status": - {"field_name": "status", - "cls": EnumOptionId}, - "template_uri": - {"field_name": "templateURI", - "cls": SubterraURI}, + "status": {"field_name": "status", "cls": EnumOptionId}, + "template_uri": {"field_name": "templateURI", "cls": SubterraURI}, "updated": "updated", "uri": "_uri", - "_unresolved": "_unresolved"} + "_unresolved": "_unresolved", + } _obj_client = "planning_client" _obj_struct = "tns4:Plan" _id_field = "plan_id" @@ -143,16 +141,13 @@ def create(cls, plan_id, plan_name, project_id, parent_id, template_id): References: Planning.createPlan """ - uri = cls.session.planning_client.service.createPlan(project_id, - plan_name, - plan_id, - parent_id, - template_id) + uri = cls.session.planning_client.service.createPlan( + project_id, plan_name, plan_id, parent_id, template_id + ) return Plan(uri=uri) @classmethod - def create_plan_template(cls, template_id, template_name, project_id, - parent_id): + def create_plan_template(cls, template_id, template_name, project_id, parent_id): """Creates a new plan template Args: @@ -169,7 +164,8 @@ def create_plan_template(cls, template_id, template_name, project_id, Planning.createPlanTemplate """ uri = cls.session.planning_client.service.createPlanTemplate( - project_id, template_name, template_id, parent_id) + project_id, template_name, template_id, parent_id + ) return Plan(uri=uri) @classmethod @@ -189,8 +185,7 @@ def delete_plans(cls, project_id, plan_ids): cls.session.planning_client.service.deletePlans(project_id, plan_ids) @classmethod - def search(cls, query, sort="plan_id", limit=-1, fields=[], - search_templates=False): + def search(cls, query, sort="plan_id", limit=-1, fields=[], search_templates=False): """search plans or plan templates Args @@ -217,20 +212,22 @@ def search(cls, query, sort="plan_id", limit=-1, fields=[], function_name = "searchPlans" if fields: function_name += "WithFields" - p_sort = cls._cls_suds_map[sort] if not isinstance( - cls._cls_suds_map[sort], dict) else \ - cls._cls_suds_map[sort]["field_name"] - parms = [query, p_sort, limit] + \ - ([cls._convert_obj_fields_to_polarion(fields)] - if fields else []) + p_sort = ( + cls._cls_suds_map[sort] + if not isinstance(cls._cls_suds_map[sort], dict) + else cls._cls_suds_map[sort]["field_name"] + ) + parms = [query, p_sort, limit] + ( + [cls._convert_obj_fields_to_polarion(fields)] if fields else [] + ) plans = [] - for sud_plan in getattr(cls.session.planning_client.service, - function_name)(*parms): + for sud_plan in getattr(cls.session.planning_client.service, function_name)( + *parms + ): plans.append(Plan(suds_object=sud_plan)) return plans - def __init__(self, plan_id=None, project_id=None, uri=None, - suds_object=None): + def __init__(self, plan_id=None, project_id=None, uri=None, suds_object=None): """Plan Constructor Args: @@ -247,29 +244,28 @@ def __init__(self, plan_id=None, project_id=None, uri=None, Planning.getPlanById Planning.getPlanByUri """ - super(self.__class__, self).__init__(obj_id=plan_id, - suds_object=suds_object) + super(self.__class__, self).__init__(obj_id=plan_id, suds_object=suds_object) if plan_id: if not project_id: - raise PyleroLibException("When plan_id is passed in, " - "project_id is required") - self._suds_object = self.session.planning_client.service. \ - getPlanById(project_id, plan_id) + raise PyleroLibException( + "When plan_id is passed in, " "project_id is required" + ) + self._suds_object = self.session.planning_client.service.getPlanById( + project_id, plan_id + ) elif uri: - self._suds_object = self.session.planning_client.service. \ - getPlanByUri(uri) + self._suds_object = self.session.planning_client.service.getPlanByUri(uri) if plan_id or uri: if getattr(self._suds_object, "_unresolvable", True): - raise PyleroLibException( - "The Plan {0} was not found.".format(plan_id)) + raise PyleroLibException("The Plan {0} was not found.".format(plan_id)) -# The parent variable is commented out, see above for explanation. -# in the event that the parent atrtribute becomes relevant, this function will -# need to be uncommented out as well -# def _fix_circular_refs(self): -# # The module references itself as a class attribute, which is not -# # allowed, so the self reference is defined here. -# self._cls_suds_map["parent"]["cls"] = self.__class__ + # The parent variable is commented out, see above for explanation. + # in the event that the parent atrtribute becomes relevant, this function will + # need to be uncommented out as well + # def _fix_circular_refs(self): + # # The module references itself as a class attribute, which is not + # # allowed, so the self reference is defined here. + # self._cls_suds_map["parent"]["cls"] = self.__class__ def add_plan_items(self, work_items): """Add plan records to the plan. @@ -287,7 +283,8 @@ def add_plan_items(self, work_items): if work_items: if not isinstance(work_items, list): raise PyleroLibException( - "work_items must be a list of _WorkItem objects") + "work_items must be a list of _WorkItem objects" + ) p_items = [] for item in work_items: wi = _WorkItem(self.project_id, work_item_id=item) @@ -307,8 +304,7 @@ def get_statistics(self): Planning.getPlanStatistics """ self._verify_obj() - suds_stat = self.session.planning_client.service.getPlanStatistics( - self.uri) + suds_stat = self.session.planning_client.service.getPlanStatistics(self.uri) return PlanStatistics(suds_object=suds_stat) def get_wiki_content(self): @@ -324,8 +320,7 @@ def get_wiki_content(self): Planning.getPlanWikiContent """ self._verify_obj() - suds_obj = self.session.planning_client.service.getPlanWikiContent( - self.uri) + suds_obj = self.session.planning_client.service.getPlanWikiContent(self.uri) return Text(suds_object=suds_obj) def remove_plan_items(self, work_items): @@ -344,7 +339,8 @@ def remove_plan_items(self, work_items): if work_items: if not isinstance(work_items, list): raise PyleroLibException( - "work_items must be a list of _WorkItem objects") + "work_items must be a list of _WorkItem objects" + ) p_items = [] for item in work_items: wi = _WorkItem(self.project_id, work_item_id=item) @@ -374,8 +370,7 @@ def set_wiki_content(self, content): suds_content = content else: suds_content = suds.null() - self.session.planning_client.service. \ - setPlanWikiContent(self.uri, suds_content) + self.session.planning_client.service.setPlanWikiContent(self.uri, suds_content) def update(self): """updates the server with the current plan content diff --git a/src/pylero/plan_record.py b/src/pylero/plan_record.py index 9e6f136..16c7193 100644 --- a/src/pylero/plan_record.py +++ b/src/pylero/plan_record.py @@ -12,13 +12,13 @@ class PlanRecord(BasePolarion): """Object to handle the Polarion WSDL tns6:PlanRecord class Attributes: - item (_WorkItem) -""" - _cls_suds_map = {"item": - {"field_name": "item", - "cls": _WorkItem}, - "uri": "_uri", - "_unresolved": "_unresolved"} + item (_WorkItem)""" + + _cls_suds_map = { + "item": {"field_name": "item", "cls": _WorkItem}, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns6:PlanRecord" diff --git a/src/pylero/plan_statistics.py b/src/pylero/plan_statistics.py index a2ad1ef..eaecbbf 100644 --- a/src/pylero/plan_statistics.py +++ b/src/pylero/plan_statistics.py @@ -23,22 +23,24 @@ class PlanStatistics(BasePolarion): progress (float) progress_as_string (string) todo (float) - todo_as_string (string) -""" - _cls_suds_map = {"done": "done", - "done_as_string": "doneAsString", - "ideal_progress": "idealProgress", - "ideal_progress_as_string": "idealProgressAsString", - "number_of_planned": "numberOfPlanned", - "number_of_resolved": "numberOfResolved", - "number_of_unresolved": "numberOfUnresolved", - "planned": "planned", - "planned_as_string": "plannedAsString", - "progress": "progress", - "progress_as_string": "progressAsString", - "todo": "todo", - "todo_as_string": "todoAsString", - "uri": "_uri", - "_unresolved": "_unresolved"} + todo_as_string (string)""" + + _cls_suds_map = { + "done": "done", + "done_as_string": "doneAsString", + "ideal_progress": "idealProgress", + "ideal_progress_as_string": "idealProgressAsString", + "number_of_planned": "numberOfPlanned", + "number_of_resolved": "numberOfResolved", + "number_of_unresolved": "numberOfUnresolved", + "planned": "planned", + "planned_as_string": "plannedAsString", + "progress": "progress", + "progress_as_string": "progressAsString", + "todo": "todo", + "todo_as_string": "todoAsString", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "planning_client" _obj_struct = "tns3:PlanStatistics" diff --git a/src/pylero/planning_constraint.py b/src/pylero/planning_constraint.py index 27156ed..5c258b4 100644 --- a/src/pylero/planning_constraint.py +++ b/src/pylero/planning_constraint.py @@ -13,14 +13,14 @@ class PlanningConstraint(BasePolarion): Attributes: constraint (EnumOptionId) - date (dateTime) -""" - _cls_suds_map = {"constraint": - {"field_name": "constraint", - "cls": EnumOptionId}, - "date": "date", - "uri": "_uri", - "_unresolved": "_unresolved"} + date (dateTime)""" + + _cls_suds_map = { + "constraint": {"field_name": "constraint", "cls": EnumOptionId}, + "date": "date", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:PlanningConstraint" diff --git a/src/pylero/priority_opt.py b/src/pylero/priority_opt.py index 49ee6dd..243ffc7 100644 --- a/src/pylero/priority_opt.py +++ b/src/pylero/priority_opt.py @@ -20,20 +20,20 @@ class PriorityOpt(BasePolarion): name (string) phantom (boolean) properties (Properties) - sequence_number (int) -""" - _cls_suds_map = {"default": "default", - "enum_id": "enumId", - "float": "float", - "hidden": "hidden", - "priority_opt_id": "id", - "name": "name", - "phantom": "phantom", - "properties": - {"field_name": "properties", - "cls": Properties}, - "sequence_number": "sequenceNumber", - "uri": "_uri", - "_unresolved": "_unresolved"} + sequence_number (int)""" + + _cls_suds_map = { + "default": "default", + "enum_id": "enumId", + "float": "float", + "hidden": "hidden", + "priority_opt_id": "id", + "name": "name", + "phantom": "phantom", + "properties": {"field_name": "properties", "cls": Properties}, + "sequence_number": "sequenceNumber", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:PriorityOpt" diff --git a/src/pylero/priority_option_id.py b/src/pylero/priority_option_id.py index 9c7fd46..e55617f 100644 --- a/src/pylero/priority_option_id.py +++ b/src/pylero/priority_option_id.py @@ -11,17 +11,14 @@ class PriorityOptionId(BasePolarion): """Object to handle the Polarion WSDL tns5:PriorityOptionId class Attributes: - id (string) -""" - _cls_suds_map = {"id": "id", - "uri": "_uri", - "_unresolved": "_unresolved"} + id (string)""" + + _cls_suds_map = {"id": "id", "uri": "_uri", "_unresolved": "_unresolved"} _id_field = "id" _obj_client = "builder_client" _obj_struct = "tns5:PriorityOptionId" - def __init__(self, id=None, uri=None, - suds_object=None): + def __init__(self, id=None, uri=None, suds_object=None): """PriorityOptionID Constructor Args: diff --git a/src/pylero/product_license.py b/src/pylero/product_license.py index 94ccde3..6e7a90c 100644 --- a/src/pylero/product_license.py +++ b/src/pylero/product_license.py @@ -23,21 +23,23 @@ class ProductLicense(BasePolarion): license_format (string) license_profile (string) mac_address (string) - named_license_data (ArrayOf_tns3_LicenseInfo) -""" - _cls_suds_map = {"concurrent_license_data": "concurrent_license_data", - "customer_company": "customerCompany", - "customer_email": "customerEmail", - "customer_name": "customerName", - "date_created": "dateCreated", - "expiration_date": "expirationDate", - "generated_by": "generatedBy", - "ip_address": "ipAddress", - "license_format": "licenseFormat", - "license_profile": "licenseProfile", - "mac_address": "macAddress", - "named_license_data": "named_license_data", - "uri": "_uri", - "_unresolved": "_unresolved"} + named_license_data (ArrayOf_tns3_LicenseInfo)""" + + _cls_suds_map = { + "concurrent_license_data": "concurrent_license_data", + "customer_company": "customerCompany", + "customer_email": "customerEmail", + "customer_name": "customerName", + "date_created": "dateCreated", + "expiration_date": "expirationDate", + "generated_by": "generatedBy", + "ip_address": "ipAddress", + "license_format": "licenseFormat", + "license_profile": "licenseProfile", + "mac_address": "macAddress", + "named_license_data": "named_license_data", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "security_client" _obj_struct = "tns3:ProductLicense" diff --git a/src/pylero/project.py b/src/pylero/project.py index 029b555..4aa0603 100644 --- a/src/pylero/project.py +++ b/src/pylero/project.py @@ -29,35 +29,33 @@ class Project(BasePolarion): project_group (ProjectGroup) project_id (string) start (date) - tracker_prefix (string) -""" - _cls_suds_map = {"active": "active", - "description": - {"field_name": "description", - "cls": Text}, - "finish": "finish", - "lead": - {"field_name": "lead", - "cls": User}, - "location": "location", - "lock_work_records_date": "lockWorkRecordsDate", - "name": "name", - "project_group": - {"field_name": "projectGroupURI", - # cls is defined in _fix_circular_refs function - "named_arg": "uri", - "sync_field": "uri"}, - "project_id": "id", - "start": "start", - "tracker_prefix": "trackerPrefix", - "uri": "_uri", - "_unresolved": "_unresolved"} + tracker_prefix (string)""" + + _cls_suds_map = { + "active": "active", + "description": {"field_name": "description", "cls": Text}, + "finish": "finish", + "lead": {"field_name": "lead", "cls": User}, + "location": "location", + "lock_work_records_date": "lockWorkRecordsDate", + "name": "name", + "project_group": { + "field_name": "projectGroupURI", + # cls is defined in _fix_circular_refs function + "named_arg": "uri", + "sync_field": "uri", + }, + "project_id": "id", + "start": "start", + "tracker_prefix": "trackerPrefix", + "uri": "_uri", + "_unresolved": "_unresolved", + } _id_field = "project_id" _obj_client = "project_client" _obj_struct = "tns2:Project" - URI_STRUCT = "subterra:data-service:objects:/default/" \ - "%(id)s${%(obj)s}%(id)s" + URI_STRUCT = "subterra:data-service:objects:/default/" "%(id)s${%(obj)s}%(id)s" @classmethod def get_context_roles(cls, location): @@ -74,8 +72,7 @@ def get_context_roles(cls, location): """ return cls.session.security_client.service.getContextRoles(location) - def __init__(self, project_id=None, suds_object=None, location=None, - uri=None): + def __init__(self, project_id=None, suds_object=None, location=None, uri=None): """Project constructor. Args: @@ -104,15 +101,16 @@ def __init__(self, project_id=None, suds_object=None, location=None, if project: self._suds_object = copy.deepcopy(project) else: - self._suds_object = self.session.project_client.service. \ - getProject(project_id) + self._suds_object = self.session.project_client.service.getProject( + project_id + ) self._cache["projects"][project_id] = self._suds_object elif location: - self._suds_object = self.session.project_client.service. \ - getProjectatLocation(location) + self._suds_object = ( + self.session.project_client.service.getProjectatLocation(location) + ) elif uri: - self._suds_object = self.session.project_client.service. \ - getProjectByURI(uri) + self._suds_object = self.session.project_client.service.getProjectByURI(uri) if project_id or location or uri: if getattr(self._suds_object, "_unresolvable", True): raise PyleroLibException("The Project was not found.") @@ -121,10 +119,11 @@ def _fix_circular_refs(self): # The module references ProjectGroup, which references this class # This is not allowed, so the self reference is defined here. from pylero.project_group import ProjectGroup + self._cls_suds_map["project_group"]["cls"] = ProjectGroup def get_categories(self): - """ method get_categories retrieves a list of Category objects + """method get_categories retrieves a list of Category objects Args: None @@ -137,8 +136,9 @@ def get_categories(self): """ self._verify_obj() categories = [] - for suds_cat in self.session.tracker_client.service. \ - getCategories(self.project_id): + for suds_cat in self.session.tracker_client.service.getCategories( + self.project_id + ): categories.append(Category(suds_object=suds_cat)) return categories @@ -156,7 +156,8 @@ def get_defined_custom_field_keys(self, work_item_type_id): """ self._verify_obj() return self.session.tracker_client.service.getDefinedCustomFieldkeys( - self.project_id, work_item_type_id) + self.project_id, work_item_type_id + ) def get_defined_custom_field_type(self, work_item_type_id, key): """method get_defined_custom_field_type gets custom field definition @@ -173,8 +174,9 @@ def get_defined_custom_field_type(self, work_item_type_id, key): Tracker.getDefinedCustomFieldType """ self._verify_obj() - suds_custom = self.session.tracker_client.service. \ - getDefinedCustomFieldType(self._uri, work_item_type_id, key) + suds_custom = self.session.tracker_client.service.getDefinedCustomFieldType( + self._uri, work_item_type_id, key + ) return CustomFieldType(suds_object=suds_custom) def get_defined_custom_field_types(self, work_item_type_id): @@ -192,8 +194,11 @@ def get_defined_custom_field_types(self, work_item_type_id): """ self._verify_obj() customs = [] - for suds_custom in self.session.tracker_client.service. \ - getDefinedCustomFieldType(self._uri, work_item_type_id): + for ( + suds_custom + ) in self.session.tracker_client.service.getDefinedCustomFieldType( + self._uri, work_item_type_id + ): customs.append(CustomFieldType(suds_object=suds_custom)) return customs @@ -210,8 +215,7 @@ def get_document_locations(self): Tracker.getDocumentLocations """ self._verify_obj() - return self.session.tracker_client.service. \ - getDocumentLocations(self.project_id) + return self.session.tracker_client.service.getDocumentLocations(self.project_id) def get_document_spaces(self): """Gets the Module/Document spaces for the project. @@ -226,8 +230,7 @@ def get_document_spaces(self): Tracker.getDocumentSpaces """ self._verify_obj() - return self.session.tracker_client.service. \ - getDocumentSpaces(self.project_id) + return self.session.tracker_client.service.getDocumentSpaces(self.project_id) def get_project_users(self): """Gets users of the project @@ -243,8 +246,9 @@ def get_project_users(self): """ self._verify_obj() users = [] - for suds_user in self.session.project_client.service. \ - getProjectUsers(self.project_id): + for suds_user in self.session.project_client.service.getProjectUsers( + self.project_id + ): users.append(User(suds_object=suds_user)) def get_test_steps_configuration(self): @@ -261,8 +265,11 @@ def get_test_steps_configuration(self): TestManagement.getTestStepsConfiguration """ self._verify_obj() - config_steps = self.session.test_management_client.service. \ - getTestStepsConfiguration(self.project_id) + config_steps = ( + self.session.test_management_client.service.getTestStepsConfiguration( + self.project_id + ) + ) return config_steps[0] def get_tests_configuration(self): @@ -279,8 +286,11 @@ def get_tests_configuration(self): TestManagement.getTestsConfiguration """ self._verify_obj() - tests_config = self.session.test_management_client.service. \ - getTestsConfiguration(self.project_id) + tests_config = ( + self.session.test_management_client.service.getTestsConfiguration( + self.project_id + ) + ) return TestsConfiguration(suds_object=tests_config) def get_wiki_spaces(self): @@ -296,5 +306,4 @@ def get_wiki_spaces(self): Tracker.getWikiSpaces """ self._verify_obj() - return self.session.tracker_client.service.getWikiSpaces( - self.project_id) + return self.session.tracker_client.service.getWikiSpaces(self.project_id) diff --git a/src/pylero/project_group.py b/src/pylero/project_group.py index 99017d7..0d5b741 100644 --- a/src/pylero/project_group.py +++ b/src/pylero/project_group.py @@ -18,22 +18,23 @@ class ProjectGroup(BasePolarion): location (Location) name (string) parent_uri (SubterraURI) - project_ids (ArrayOfstring) -""" - _cls_suds_map = {"group_uris": - {"field_name": "groupURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "location": "location", - "name": "name", - "parent_uri": - {"field_name": "parentURI", - "cls": SubterraURI}, - "project_ids": "projectIDs", - "uri": "_uri", - "_unresolved": "_unresolved"} + project_ids (ArrayOfstring)""" + + _cls_suds_map = { + "group_uris": { + "field_name": "groupURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "location": "location", + "name": "name", + "parent_uri": {"field_name": "parentURI", "cls": SubterraURI}, + "project_ids": "projectIDs", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "project_client" _obj_struct = "tns2:ProjectGroup" @@ -50,8 +51,7 @@ def get_root_project_group(cls): References: Project.getRootProjectGroup """ - return cls(suds_object=cls.session.project_client.service. - getRootProjectGroup()) + return cls(suds_object=cls.session.project_client.service.getRootProjectGroup()) def __init__(self, uri=None, location=None, suds_object=None): """ProjectGroup constructor. @@ -73,11 +73,11 @@ def __init__(self, uri=None, location=None, suds_object=None): """ super(self.__class__, self).__init__(suds_object=suds_object) if uri: - self._suds_object = self.session.project_client.service. \ - getProjectGroup(uri) + self._suds_object = self.session.project_client.service.getProjectGroup(uri) elif location: - self._suds_object = self.session.project_client.service. \ - getProjectGroupAtLocation(location) + self._suds_object = ( + self.session.project_client.service.getProjectGroupAtLocation(location) + ) def get_contained_groups(self): """Gets all project groups located directly below the project group. @@ -93,8 +93,9 @@ def get_contained_groups(self): """ self._verify_obj() groups = [] - for suds_group in self.session.project_client.service. \ - getContainedGroups(self.uri): + for suds_group in self.session.project_client.service.getContainedGroups( + self.uri + ): groups.append(self.__class__(suds_object=suds_group)) return groups @@ -112,8 +113,9 @@ def get_contained_projects(self): """ self._verify_obj() projects = [] - for suds_project in self.session.project_client.service. \ - getContainedProjects(self.uri): + for suds_project in self.session.project_client.service.getContainedProjects( + self.uri + ): projects.append(Project(suds_object=suds_project)) return projects @@ -131,7 +133,8 @@ def get_deep_contained_projects(self): """ self._verify_obj() projects = [] - for suds_project in self.session.project_client.service. \ - getDeepContainedProjects(self.uri): + for ( + suds_project + ) in self.session.project_client.service.getDeepContainedProjects(self.uri): projects.append(Project(suds_object=suds_project)) return projects diff --git a/src/pylero/properties.py b/src/pylero/properties.py index 86b1bb1..aedfed5 100644 --- a/src/pylero/properties.py +++ b/src/pylero/properties.py @@ -11,10 +11,12 @@ class Properties(BasePolarion): """Object to handle the Polarion WSDL tns4:Properties class Attributes: - property (property) -""" - _cls_suds_map = {"property": "property", - "uri": "_uri", - "_unresolved": "_unresolved"} + property (property)""" + + _cls_suds_map = { + "property": "property", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns4:Properties" diff --git a/src/pylero/property.py b/src/pylero/property.py index e18f33d..40f3225 100644 --- a/src/pylero/property.py +++ b/src/pylero/property.py @@ -12,11 +12,13 @@ class Property(BasePolarion): Attributes: key (string) - value (string) -""" - _cls_suds_map = {"key": "key", - "value": "value", - "uri": "_uri", - "_unresolved": "_unresolved"} + value (string)""" + + _cls_suds_map = { + "key": "key", + "value": "value", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns4:property" diff --git a/src/pylero/revision.py b/src/pylero/revision.py index 0a36910..8e73bc0 100644 --- a/src/pylero/revision.py +++ b/src/pylero/revision.py @@ -19,22 +19,25 @@ class Revision(BasePolarion): linked_work_item_uris (ArrayOfSubterraURI) message (string) name (string) - repository_name (string) -""" - _cls_suds_map = {"author": "author", - "created": "created", - "internal_commit": "internalCommit", - "linked_work_item_uris": - {"field_name": "linkedWorkItemURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "message": "message", - "name": "name", - "repository_name": "repositoryName", - "uri": "_uri", - "_unresolved": "_unresolved"} + repository_name (string)""" + + _cls_suds_map = { + "author": "author", + "created": "created", + "internal_commit": "internalCommit", + "linked_work_item_uris": { + "field_name": "linkedWorkItemURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "message": "message", + "name": "name", + "repository_name": "repositoryName", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns4:Revision" @@ -65,10 +68,12 @@ def query(cls, query, sort="name", fields=["name"], query_uris=False): """ if query_uris: return cls.session.tracker_client.service.queryRevisionUris( - query, sort, False) + query, sort, False + ) else: revs = cls.session.tracker_client.service.queryRevisions( - query, sort, fields) + query, sort, fields + ) lst_rev = [Revision(suds_object=rev) for rev in revs] return lst_rev diff --git a/src/pylero/server.py b/src/pylero/server.py index 7065d46..e8de874 100644 --- a/src/pylero/server.py +++ b/src/pylero/server.py @@ -14,8 +14,16 @@ class Server(object): session that is used to connect to the server. """ - def __init__(self, url, login, password, default_project=None, - relogin_timeout=60, timeout=120, cert_path=None): + def __init__( + self, + url, + login, + password, + default_project=None, + relogin_timeout=60, + timeout=120, + cert_path=None, + ): """An object that defines the properties of the Polarion server to connect to. diff --git a/src/pylero/session.py b/src/pylero/session.py index a902e54..3080d3c 100644 --- a/src/pylero/session.py +++ b/src/pylero/session.py @@ -20,13 +20,14 @@ logger = logging.getLogger(__name__) # We create a logger in order to intercept log records from suds.client -suds_logger = logging.getLogger('suds.client') +suds_logger = logging.getLogger("suds.client") CERT_PATH = None # Regular expression to catch SOAP message containing password field -REGEX_SOAP_MESSAGE_PASSWORD_FIELD = \ - re.compile(r'()(.*)().*') +REGEX_SOAP_MESSAGE_PASSWORD_FIELD = re.compile( + r"()(.*)().*" +) class ListenFilter(logging.Filter): @@ -36,10 +37,10 @@ def filter(self, record): """ # We assume that this message contains the password in plaintext # which as part of SOAP message - if ' self._server.relogin_timeout and not \ - sc.service.hasSubject(): + if duration > self._server.relogin_timeout and not sc.service.hasSubject(): logger.debug("Session expired, trying to log in again") self._login() else: @@ -192,32 +198,34 @@ def __init__(self, url, enclosing_session, timeout): timeout (int): The HTTP timeout of the connection """ plugin = SoapNull() - self._suds_client = suds.client.Client( - url, - plugins=[plugin], - timeout=timeout) + self._suds_client = suds.client.Client(url, plugins=[plugin], timeout=timeout) self._enclosing_session = enclosing_session def __getattr__(self, attr): # every time a client function is called, this verifies that there is # still an active connection and if not, it reconnects. logger.debug("attr={0} self={1}".format(attr, self.__dict__)) - if attr == "service" and self._enclosing_session and \ - self._enclosing_session._session_id_header is not None: - logger.debug("Calling hook before _suds_client_wrapper.service " - "access") + if ( + attr == "service" + and self._enclosing_session + and self._enclosing_session._session_id_header is not None + ): + logger.debug("Calling hook before _suds_client_wrapper.service " "access") self._enclosing_session._reauth() self._suds_client.set_options( - soapheaders=self._enclosing_session._session_id_header) + soapheaders=self._enclosing_session._session_id_header + ) # for some reason adding the cookiejar didn't work, so the # cookie is being added to the header manually. # self._suds_client.options.transport.cookiejar = \ # self._enclosing_session._cookies # adding the RouteID cookie, if it exists to the headers. hostname = urlparse(self._enclosing_session._server.url).hostname - route = self._enclosing_session._cookies._cookies \ - .get(hostname, {}).get("/", {}).get("ROUTEID") + route = ( + self._enclosing_session._cookies._cookies.get(hostname, {}) + .get("/", {}) + .get("ROUTEID") + ) if route: - self._suds_client.options.headers["Cookie"] = \ - "ROUTEID=%s" % route.value + self._suds_client.options.headers["Cookie"] = "ROUTEID=%s" % route.value return getattr(self._suds_client, attr) diff --git a/src/pylero/signature.py b/src/pylero/signature.py index 692d622..ee00bd2 100644 --- a/src/pylero/signature.py +++ b/src/pylero/signature.py @@ -17,17 +17,15 @@ class Signature(BasePolarion): signed_revision (string) signer_role (string) verdict (EnumOptionId) - verdict_time (dateTime) -""" - _cls_suds_map = {"verdict": - {"field_name": "verdict", - "cls": EnumOptionId}, - "signed_revision": "signedRevision", - "verdict_time": "verdictTime", - "signer_role": "signerRole", - "signed_by": - {"field_name": "signedBy", - "cls": User}} + verdict_time (dateTime)""" + + _cls_suds_map = { + "verdict": {"field_name": "verdict", "cls": EnumOptionId}, + "signed_revision": "signedRevision", + "verdict_time": "verdictTime", + "signer_role": "signerRole", + "signed_by": {"field_name": "signedBy", "cls": User}, + } _obj_client = "test_management_client" _obj_struct = "tns4:Signature" diff --git a/src/pylero/signature_context.py b/src/pylero/signature_context.py index d7e007c..83d6ee2 100644 --- a/src/pylero/signature_context.py +++ b/src/pylero/signature_context.py @@ -17,19 +17,20 @@ class SignatureContext(BasePolarion): signatures (ArrayOfSignature) target_status_id (string) transition_data_revision (string) - user (User) -""" - _cls_suds_map = {"transition_data_revision": "transitionDataRevision", - "signatures": - {"field_name": "signatures", - "is_array": True, - "cls": Signature, - "arr_cls": ArrayOfSignature, - "inner_field_name": "Signature"}, - "target_status_id": "targetStatusId", - "user": - {"field_name": "user", - "cls": User}} + user (User)""" + + _cls_suds_map = { + "transition_data_revision": "transitionDataRevision", + "signatures": { + "field_name": "signatures", + "is_array": True, + "cls": Signature, + "arr_cls": ArrayOfSignature, + "inner_field_name": "Signature", + }, + "target_status_id": "targetStatusId", + "user": {"field_name": "user", "cls": User}, + } _obj_client = "test_management_client" _obj_struct = "tns4:SignatureContext" diff --git a/src/pylero/signature_data.py b/src/pylero/signature_data.py index 6536591..40feb8f 100644 --- a/src/pylero/signature_data.py +++ b/src/pylero/signature_data.py @@ -13,11 +13,11 @@ class SignatureData(BasePolarion): Attributes: target_status_id (string) - verdict (EnumOptionId) -""" - _cls_suds_map = {"target_status_id": "targetStatusId", - "verdict": - {"field_name": "verdict", - "cls": EnumOptionId}} + verdict (EnumOptionId)""" + + _cls_suds_map = { + "target_status_id": "targetStatusId", + "verdict": {"field_name": "verdict", "cls": EnumOptionId}, + } _obj_client = "builder_client" _obj_struct = "tns5:SignatureData" diff --git a/src/pylero/test_record.py b/src/pylero/test_record.py index 25eaf30..60bb748 100644 --- a/src/pylero/test_record.py +++ b/src/pylero/test_record.py @@ -28,47 +28,47 @@ class TestRecord(BasePolarion): result (EnumOptionId) test_case_revision (string) test_case_id (string) - test_step_results (ArrayOfTestStepResult) -""" + test_step_results (ArrayOfTestStepResult)""" _cls_suds_map = { - "attachments": - {"field_name": "attachments", - "is_array": True, - "cls": TestRunAttachment, - "arr_cls": ArrayOfTestRunAttachment, - "inner_field_name": "TestRunAttachment"}, - "comment": - {"field_name": "comment", - "cls": Text}, - "defect_case_id": - {"field_name": "defectURI", - "cls": _WorkItem, - "named_arg": "uri", - "sync_field": "uri"}, + "attachments": { + "field_name": "attachments", + "is_array": True, + "cls": TestRunAttachment, + "arr_cls": ArrayOfTestRunAttachment, + "inner_field_name": "TestRunAttachment", + }, + "comment": {"field_name": "comment", "cls": Text}, + "defect_case_id": { + "field_name": "defectURI", + "cls": _WorkItem, + "named_arg": "uri", + "sync_field": "uri", + }, "duration": "duration", "executed": "executed", - "executed_by": - {"field_name": "executedByURI", - "cls": User, - "named_arg": "uri", - "sync_field": "uri"}, - "result": - {"field_name": "result", - "cls": EnumOptionId, - "enum_id": "result"}, - "test_case_id": - {"field_name": "testCaseURI", - "cls": _WorkItem, - "named_arg": "uri", - "sync_field": "uri"}, + "executed_by": { + "field_name": "executedByURI", + "cls": User, + "named_arg": "uri", + "sync_field": "uri", + }, + "result": {"field_name": "result", "cls": EnumOptionId, "enum_id": "result"}, + "test_case_id": { + "field_name": "testCaseURI", + "cls": _WorkItem, + "named_arg": "uri", + "sync_field": "uri", + }, "test_case_revision": "testCaseRevision", - "test_step_results": - {"field_name": "testStepResults", - "is_array": True, - "cls": TestStepResult, - "arr_cls": ArrayOfTestStepResult, - "inner_field_name": "TestStepResult"}} + "test_step_results": { + "field_name": "testStepResults", + "is_array": True, + "cls": TestStepResult, + "arr_cls": ArrayOfTestStepResult, + "inner_field_name": "TestStepResult", + }, + } _obj_client = "test_management_client" _obj_struct = "tns3:TestRecord" _id_field = "test_case_id" @@ -80,10 +80,12 @@ def __init__(self, project_id=None, test_case_id=None, suds_object=None): def _fix_circular_refs(self): # need to pass in the project_id parm to the Work Item, # but it is not given before instatiation - self._cls_suds_map["test_case_id"]["additional_parms"] = \ - {"project_id": self.project_id} - self._cls_suds_map["defect_case_id"]["additional_parms"] = \ - {"project_id": self.project_id} + self._cls_suds_map["test_case_id"]["additional_parms"] = { + "project_id": self.project_id + } + self._cls_suds_map["defect_case_id"]["additional_parms"] = { + "project_id": self.project_id + } class ArrayOfTestRecord(BasePolarion): diff --git a/src/pylero/test_run.py b/src/pylero/test_run.py index 0dfb260..6644a17 100644 --- a/src/pylero/test_run.py +++ b/src/pylero/test_run.py @@ -32,86 +32,106 @@ from pylero.user import User from pylero.work_item import _WorkItem from pylero.work_item import TestCase + # Build is used in custom fields. # Plan is used in custom fields. def generate_description(test_run, test_case, test_record): - tr_html = "Test Run: " \ - "
".format(test_run.test_run_id) - tc_html = "Test Case: " \ - "
".format(test_case.work_item_id) - table_cell_style = "style=\"text-align: left; padding: 10px; " \ - "vertical-align: top; background-color: #ffffff;\"" - table_row_style = "style=\"border-bottom: 1px solid #f0f0f0;\"" - columns = ["", "#", "Step", - "Expected Result", - "Actual Result"] - test_step_results = {"passed": "", - "failed": "", - "blocked": "" - ""} - table_header = "{0}" \ - .format("".join(["".format(table_cell_style, column) - for column in columns])) - verdict = "
{1}
"\ - "" \ - "
Test Case Verdict:
" \ - "Failed {0}
" \ - .format(test_record.comment) + tr_html = ( + 'Test Run: ' + "
".format(test_run.test_run_id) + ) + tc_html = ( + 'Test Case: ' + "
".format(test_case.work_item_id) + ) + table_cell_style = ( + 'style="text-align: left; padding: 10px; ' + 'vertical-align: top; background-color: #ffffff;"' + ) + table_row_style = 'style="border-bottom: 1px solid #f0f0f0;"' + columns = [ + "", + "#", + 'Step', + 'Expected Result', + "Actual Result", + ] + test_step_results = { + "passed": '", + "failed": '', + "blocked": '' + "", + } + table_header = ( + '{0}'.format( + "".join( + [ + "".format(table_cell_style, column) + for column in columns + ] + ) + ) + ) + verdict = ( + '
{1}
' + '" + "
Test Case Verdict:
' + "Failed {0}
".format(test_record.comment) + ) table_rows = "" for step in range(len(test_record.test_step_results)): - table_rows += "" \ - "{2}" \ - "{3}" \ - "{4}" \ - "{5}" \ - "{6}" \ - "".format(table_row_style, - table_cell_style, - test_step_results. - get(test_record.test_step_results[step] - .result), - step + 1, - test_case.test_steps.steps[step].values[0] - .content, - test_case.test_steps.steps[step].values[1] - .content, - test_record.test_step_results[step] - .comment) + table_rows += ( + "" + "{2}" + "{3}" + "{4}" + "{5}" + "{6}" + "".format( + table_row_style, + table_cell_style, + test_step_results.get(test_record.test_step_results[step].result), + step + 1, + test_case.test_steps.steps[step].values[0].content, + test_case.test_steps.steps[step].values[1].content, + test_record.test_step_results[step].comment, + ) + ) content = tr_html + tc_html + table_header + table_rows + verdict return content @@ -119,11 +139,11 @@ def generate_description(test_run, test_case, test_record): def create_incident_report(test_run, test_record, test_case): project_id = test_run.project_id - status = 'open' + status = "open" project = Project(project_id) tconf = project.get_tests_configuration() defectWorkItemType = tconf.defect_work_item_type - title = 'Failed: ' + test_case.title + title = "Failed: " + test_case.title description = generate_description(test_run, test_case, test_record) kwarg_dict = {} @@ -132,8 +152,9 @@ def create_incident_report(test_run, test_record, test_case): for prop in tconf.fields_to_copy_from_test_run_to_linked_defect.property: kwarg_dict[prop.value] = getattr(test_run, prop.key) - incident_report = _WorkItem.create(project_id, defectWorkItemType, title, - description, status, **kwarg_dict) + incident_report = _WorkItem.create( + project_id, defectWorkItemType, title, description, status, **kwarg_dict + ) incident_report.add_linked_item(test_case.work_item_id, "triggered_by") return incident_report.work_item_id @@ -172,74 +193,84 @@ class TestRun(BasePolarion): updated custom_fields """ + _cls_suds_map = { - "attachments": - {"field_name": "attachments", - "is_array": True, - "cls": TestRunAttachment, - "arr_cls": ArrayOfTestRunAttachment, - "inner_field_name": "TestRunAttachment"}, - "author": - {"field_name": "authorURI", - "cls": User, - "named_arg": "uri", - "sync_field": "uri"}, + "attachments": { + "field_name": "attachments", + "is_array": True, + "cls": TestRunAttachment, + "arr_cls": ArrayOfTestRunAttachment, + "inner_field_name": "TestRunAttachment", + }, + "author": { + "field_name": "authorURI", + "cls": User, + "named_arg": "uri", + "sync_field": "uri", + }, "created": "created", - "document": - {"field_name": "document", - "cls": Document}, + "document": {"field_name": "document", "cls": Document}, "finished_on": "finishedOn", "group_id": "groupId", "test_run_id": "id", "is_template": "isTemplate", "keep_in_history": "keepInHistory", "location": "location", - "project_id": - {"field_name": "projectURI", - "cls": Project, - "named_arg": "uri", - "sync_field": "uri"}, + "project_id": { + "field_name": "projectURI", + "cls": Project, + "named_arg": "uri", + "sync_field": "uri", + }, "query": "query", - "_records": - {"field_name": "records", - "is_array": True, - "cls": TestRecord, - "arr_cls": ArrayOfTestRecord, - "inner_field_name": "TestRecord"}, - "select_test_cases_by": - {"field_name": "selectTestCasesBy", - "cls": EnumOptionId, - "enum_id": "testrun-selectTestCasesBy"}, - "status": - {"field_name": "status", - "cls": EnumOptionId, - "enum_id": "testing/testrun-status"}, - "summary_defect": - {"field_name": "summaryDefectURI", - "cls": _WorkItem, - "named_arg": "uri", - "sync_field": "uri"}, + "_records": { + "field_name": "records", + "is_array": True, + "cls": TestRecord, + "arr_cls": ArrayOfTestRecord, + "inner_field_name": "TestRecord", + }, + "select_test_cases_by": { + "field_name": "selectTestCasesBy", + "cls": EnumOptionId, + "enum_id": "testrun-selectTestCasesBy", + }, + "status": { + "field_name": "status", + "cls": EnumOptionId, + "enum_id": "testing/testrun-status", + }, + "summary_defect": { + "field_name": "summaryDefectURI", + "cls": _WorkItem, + "named_arg": "uri", + "sync_field": "uri", + }, "title": "title", - "template": - {"field_name": "templateURI", - "named_arg": "uri", - "sync_field": "uri"}, - "type": - {"field_name": "type", - "cls": EnumOptionId, - "enum_id": "testing/testrun-type"}, + "template": { + "field_name": "templateURI", + "named_arg": "uri", + "sync_field": "uri", + }, + "type": { + "field_name": "type", + "cls": EnumOptionId, + "enum_id": "testing/testrun-type", + }, "updated": "updated", # the custom field attribute has been changed to be a protected attr. # All interaction with custom fields should be done directly with the # derived attribute. - "_custom_fields": - {"field_name": "customFields", - "is_array": True, - "cls": Custom, - "arr_cls": ArrayOfCustom, - "inner_field_name": "Custom"}, + "_custom_fields": { + "field_name": "customFields", + "is_array": True, + "cls": Custom, + "arr_cls": ArrayOfCustom, + "inner_field_name": "Custom", + }, "uri": "_uri", - "_unresolvable": "_unresolvable"} + "_unresolvable": "_unresolvable", + } _id_field = "test_run_id" _obj_client = "test_management_client" _obj_struct = "tns3:TestRun" @@ -247,7 +278,7 @@ class TestRun(BasePolarion): @property def records(self): - """ function to return all the test records of a TestRun. + """function to return all the test records of a TestRun. The records array for dynamic queries/documents only includes executed records. This returns the unexecuted ones as well. @@ -265,18 +296,16 @@ def records(self): if "Doc" in self.select_test_cases_by: cases = self.document.get_work_items(None, True) elif "Query" in self.select_test_cases_by: - cases = _WorkItem.query( - self.query + " AND project.id:" + self.project_id) + cases = _WorkItem.query(self.query + " AND project.id:" + self.project_id) else: - raise PyleroLibException("Only Test Runs based on Docs or" - " Queries can be dynamic") + raise PyleroLibException( + "Only Test Runs based on Docs or" " Queries can be dynamic" + ) executed_ids = [rec.test_case_id for rec in self._records] test_recs = self._records for case in cases: - if case.work_item_id not in executed_ids \ - and case.type != "heading": - test_recs.append( - TestRecord(self.project_id, case.work_item_id)) + if case.work_item_id not in executed_ids and case.type != "heading": + test_recs.append(TestRecord(self.project_id, case.work_item_id)) return test_recs @records.setter @@ -285,8 +314,7 @@ def records(self, val): @classmethod @tx_wrapper - def create(cls, project_id, test_run_id=None, template=None, title=None, - **kwargs): + def create(cls, project_id, test_run_id=None, template=None, title=None, **kwargs): """class method create for creating a new test run in Polarion Args: @@ -318,12 +346,13 @@ def create(cls, project_id, test_run_id=None, template=None, title=None, if not template: raise PyleroLibException("Template is required") if title: - uri = cls.session.test_management_client.service.\ - createTestRunWithTitle( - project_id, test_run_id or title, title, template) + uri = cls.session.test_management_client.service.createTestRunWithTitle( + project_id, test_run_id or title, title, template + ) else: uri = cls.session.test_management_client.service.createTestRun( - project_id, test_run_id, template) + project_id, test_run_id, template + ) if uri: run = cls(uri=uri) run.verify_params(**kwargs) @@ -336,10 +365,16 @@ def create(cls, project_id, test_run_id=None, template=None, title=None, @classmethod @tx_wrapper - def create_template(cls, project_id, template_id, - parent_template_id="Empty", - select_test_cases_by=None, query=None, - doc_with_space=None, **kwargs): # , test_case_ids=[]): + def create_template( + cls, + project_id, + template_id, + parent_template_id="Empty", + select_test_cases_by=None, + query=None, + doc_with_space=None, + **kwargs + ): # , test_case_ids=[]): # see comment below regarding test_case)ids. """class method create_template for creating a new template in Polarion @@ -381,7 +416,7 @@ def create_template(cls, project_id, template_id, tr.query = query if doc_with_space: tr.document = Document(project_id, doc_with_space) -# TODO: This should work as soon as Polarion implements Change Request REQ-6334 + # TODO: This should work as soon as Polarion implements Change Request REQ-6334 # if test_case_ids: # for test_case_id in test_case_ids: # tr.add_test_record_by_object(testrec.TestRecord( @@ -392,8 +427,15 @@ def create_template(cls, project_id, template_id, return TestRun(tr.test_run_id, project_id=project_id) @classmethod - def search(cls, query, fields=["test_run_id"], sort="test_run_id", - limit=None, search_templates=False, project_id=None): + def search( + cls, + query, + fields=["test_run_id"], + sort="test_run_id", + limit=None, + search_templates=False, + project_id=None, + ): """class method search executes the given query and returns the results Args: @@ -424,9 +466,9 @@ def search(cls, query, fields=["test_run_id"], sort="test_run_id", test_management.searchTestRunsWithFieldsLimited """ -# The Polarion functions with limited seem to be the same as without limited -# when -1 is passed in as limit. Because of this, the wrapper will not -# implement the functions without limited. + # The Polarion functions with limited seem to be the same as without limited + # when -1 is passed in as limit. Because of this, the wrapper will not + # implement the functions without limited. project_id = project_id or cls.default_project query += " AND project.id:%s" % (project_id) @@ -434,9 +476,11 @@ def search(cls, query, fields=["test_run_id"], sort="test_run_id", # doing so setting all the class attribute (including 'customFields'). TestRun(project_id=project_id) function_name = "search" - p_sort = cls._cls_suds_map[sort] if not isinstance( - cls._cls_suds_map[sort], dict) else \ - cls._cls_suds_map[sort]["field_name"] + p_sort = ( + cls._cls_suds_map[sort] + if not isinstance(cls._cls_suds_map[sort], dict) + else cls._cls_suds_map[sort]["field_name"] + ) parms = [query, p_sort] if search_templates: function_name += "TestRunTemplates" @@ -450,15 +494,15 @@ def search(cls, query, fields=["test_run_id"], sort="test_run_id", function_name += "Limited" parms.append(limit) test_runs = [] - results = getattr(cls.session.test_management_client.service, - function_name)(*parms) + results = getattr(cls.session.test_management_client.service, function_name)( + *parms + ) for suds_obj in results: tr = TestRun(suds_object=suds_obj) test_runs.append(tr) return test_runs - def __init__(self, test_run_id=None, suds_object=None, project_id=None, - uri=None): + def __init__(self, test_run_id=None, suds_object=None, project_id=None, uri=None): """TestRun constructor. Args: @@ -483,17 +527,23 @@ def __init__(self, test_run_id=None, suds_object=None, project_id=None, super(self.__class__, self).__init__(test_run_id, suds_object) if test_run_id: if not project_id: - raise PyleroLibException("When test_run_id is passed in, " - "project_id is required") - self._suds_object = self.session.test_management_client.service. \ - getTestRunById(project_id, test_run_id) + raise PyleroLibException( + "When test_run_id is passed in, " "project_id is required" + ) + self._suds_object = ( + self.session.test_management_client.service.getTestRunById( + project_id, test_run_id + ) + ) elif uri: - self._suds_object = self.session.test_management_client.service. \ - getTestRunByUri(uri) + self._suds_object = ( + self.session.test_management_client.service.getTestRunByUri(uri) + ) if test_run_id or uri: if getattr(self._suds_object, "_unresolvable", True): raise PyleroLibException( - "The Test Run {0} was not found.".format(test_run_id)) + "The Test Run {0} was not found.".format(test_run_id) + ) def _fix_circular_refs(self): # a class can't reference itself as a class attribute so it is @@ -524,8 +574,9 @@ def _custom_field_types(self, field_type): field_type = field_type.split("[")[0] if field_type.startswith("@"): # an enum based on an object - return [globals()[x] for x in globals() - if x.lower() == field_type[1:].lower()][0] + return [ + globals()[x] for x in globals() if x.lower() == field_type[1:].lower() + ][0] else: # a regular enum return field_type @@ -547,15 +598,17 @@ def get_defined_custom_field_types(cls, project_id): testmanagement.getDefinedTestRunCustomFieldTypes """ if not cls._custom_field_cache[project_id]: - cfts = cls.session.test_management_client.service. \ - getDefinedTestRunCustomFieldTypes(project_id) + cfts = cls.session.test_management_client.service.getDefinedTestRunCustomFieldTypes( + project_id + ) else: cfts = cls._custom_field_cache[project_id] - results = [CustomFieldType(suds_object=item) - if isinstance(item, - CustomFieldType()._suds_object.__class__) - else EnumCustomFieldType(suds_object=item) - for item in cfts] + results = [ + CustomFieldType(suds_object=item) + if isinstance(item, CustomFieldType()._suds_object.__class__) + else EnumCustomFieldType(suds_object=item) + for item in cfts + ] return results def _cache_custom_fields(self, project_id): @@ -578,12 +631,14 @@ def _cache_custom_fields(self, project_id): self._custom_field_cache[project_id][key] = {} self._custom_field_cache[project_id][key]["type"] = f_type self._custom_field_cache[project_id][key]["required"] = getattr( - result, "required", False) + result, "required", False + ) self._custom_field_cache[project_id][key]["multi"] = getattr( - result, "multi", False) + result, "multi", False + ) def _add_custom_fields(self, project_id): - """ This generates object attributes, with validation, so that custom + """This generates object attributes, with validation, so that custom fields can be related to as regular attributes. It takes the custom fields from the cache and calls the cache function if the values are not already there. @@ -620,11 +675,16 @@ def _add_custom_fields(self, project_id): else: self._cls_suds_map[field]["cls"] = EnumOptionId self._cls_suds_map[field]["enum_id"] = cache[field]["type"] - if isinstance(cache[field]["type"], type) and "project_id" in \ - cache[field]["type"].__init__.__code__.co_varnames[ - :cache[field]["type"].__init__.__code__.co_argcount]: - self._cls_suds_map[field]["additional_parms"] = \ - {"project_id": project_id} + if ( + isinstance(cache[field]["type"], type) + and "project_id" + in cache[field]["type"].__init__.__code__.co_varnames[ + : cache[field]["type"].__init__.__code__.co_argcount + ] + ): + self._cls_suds_map[field]["additional_parms"] = { + "project_id": project_id + } def _get_index_of_test_record(self, test_case_id): # specific functions request the index of the test record within the @@ -640,8 +700,10 @@ def _get_index_of_test_record(self, test_case_id): index += 1 if test_case_id in test_record._suds_object.testCaseURI: return index - raise PyleroLibException("The Test Case is either not part of " - "this TestRun or has not been executed") + raise PyleroLibException( + "The Test Case is either not part of " + "this TestRun or has not been executed" + ) def _status_change(self): # load a new object to test if the status should be changed. @@ -669,16 +731,17 @@ def _verify_record_count(self, record_index): # verifies the number of records is not less then the index given. self._verify_obj() if record_index > (len(self.records) - 1): - raise PyleroLibException("There are only {0} test records". - format(len(self.records))) + raise PyleroLibException( + "There are only {0} test records".format(len(self.records)) + ) def _verify_test_step_count(self, record_index, test_step_index): # verifies the number of test steps is not less then the index given. self._verify_record_count(record_index) - if test_step_index > \ - (len(self.records[record_index].test_step_results) - 1): - raise PyleroLibException("There are only {0} test records". - format(len(self.records))) + if test_step_index > (len(self.records[record_index].test_step_results) - 1): + raise PyleroLibException( + "There are only {0} test records".format(len(self.records)) + ) def add_attachment_to_test_record(self, test_case_id, path, title): """method add_attachment_to_test_record, adds the given attachment to @@ -703,9 +766,9 @@ def add_attachment_to_test_record(self, test_case_id, path, title): self._verify_record_count(record_index) data = self._get_file_data(path) filename = os.path.basename(path) - self.session.test_management_client.service. \ - addAttachmentToTestRecord(self.uri, record_index, filename, - title, data) + self.session.test_management_client.service.addAttachmentToTestRecord( + self.uri, record_index, filename, title, data + ) def add_attachment(self, path, title): """method add_attachment adds the given attachment to the current @@ -727,11 +790,11 @@ def add_attachment(self, path, title): self._verify_obj() data = self._get_file_data(path) filename = os.path.basename(path) - self.session.test_management_client.service. \ - addAttachmentToTestRun(self.uri, filename, title, data) + self.session.test_management_client.service.addAttachmentToTestRun( + self.uri, filename, title, data + ) - def add_attachment_to_test_step(self, test_case_id, test_step_index, - path, title): + def add_attachment_to_test_step(self, test_case_id, test_step_index, path, title): """method add_attachment_to_test_step, adds the given attachment to the specified test step of the specified test record @@ -757,7 +820,8 @@ def add_attachment_to_test_step(self, test_case_id, test_step_index, data = self._get_file_data(path) filename = os.path.basename(path) self.session.test_management_client.service.addAttachmentToTestStep( - self.uri, record_index, test_step_index, filename, title, data) + self.uri, record_index, test_step_index, filename, title, data + ) def _check_test_record_exists(self, test_case_id): """Searches the test run to see if the case is already a member of it @@ -778,21 +842,29 @@ def _check_test_record_exists(self, test_case_id): None """ check_tr = TestRun.search( - 'project.id:%s AND id:"%s" AND %s' % - (self.project_id, self.test_run_id, test_case_id)) + 'project.id:%s AND id:"%s" AND %s' + % (self.project_id, self.test_run_id, test_case_id) + ) if len(check_tr) not in [0, 1]: raise PyleroLibException( - "The search function did not work as expected. Please report.") + "The search function did not work as expected. Please report." + ) elif len(check_tr) == 1: - raise PyleroLibException( - "This test case is already part of the test run") + raise PyleroLibException("This test case is already part of the test run") else: return None @tx_wrapper - def add_test_record_by_fields(self, test_case_id, test_result, - test_comment, executed_by, executed, - duration, defect_work_item_id=None): + def add_test_record_by_fields( + self, + test_case_id, + test_result, + test_comment, + executed_by, + executed, + duration, + defect_work_item_id=None, + ): """method add_test_record_by_fields, adds a test record for the given test case based on the result fields passed in. When a test record is added, it changes the test run status to @@ -820,8 +892,7 @@ def add_test_record_by_fields(self, test_case_id, test_result, self._verify_obj() self.check_valid_field_values(test_result, "result", {}) if not executed or not test_result: - raise PyleroLibException( - "executed and test_result require values") + raise PyleroLibException("executed and test_result require values") testrec = TestRecord(self.project_id, test_case_id) testrec.result = test_result testrec.comment = test_comment @@ -833,9 +904,7 @@ def add_test_record_by_fields(self, test_case_id, test_result, self.add_test_record_by_object(testrec) @tx_wrapper - def add_test_record_by_object(self, - test_record, - manual_state_change=False): + def add_test_record_by_object(self, test_record, manual_state_change=False): """method add_test_record_by_object, adds a test record for the given test case based on the TestRecord object passed in. In addition, the test run is checked for completeness and the test @@ -861,11 +930,12 @@ def add_test_record_by_object(self, elif isinstance(test_record, TestRecord()._suds_object.__class__): suds_object = test_record if test_record.result == "failed" and not test_record.defect_case_id: - test_record.defect_case_id = \ - create_incident_report(self, test_record, - TestCase(work_item_id=test_case_id)) + test_record.defect_case_id = create_incident_report( + self, test_record, TestCase(work_item_id=test_case_id) + ) self.session.test_management_client.service.addTestRecordToTestRun( - self.uri, suds_object) + self.uri, suds_object + ) if manual_state_change: self.update() @@ -891,11 +961,13 @@ def create_summary_defect(self, defect_template_id=None): self._verify_obj() defect_template_uri = None if defect_template_id: - suds_defect_template = _WorkItem(work_item_id=defect_template_id, - project_id=self.project_id) + suds_defect_template = _WorkItem( + work_item_id=defect_template_id, project_id=self.project_id + ) defect_template_uri = suds_defect_template._uri - wi_uri = self.session.test_management_client.service. \ - createSummaryDefect(self.uri, defect_template_uri) + wi_uri = self.session.test_management_client.service.createSummaryDefect( + self.uri, defect_template_uri + ) return _WorkItem(uri=wi_uri) def delete_attachment_from_test_record(self, test_case_id, filename): @@ -914,11 +986,11 @@ def delete_attachment_from_test_record(self, test_case_id, filename): """ record_index = self._get_index_of_test_record(test_case_id) self._verify_record_count(record_index) - self.session.test_management_client.service. \ - deleteAttachmentFromTestRecord(self.uri, record_index, filename) + self.session.test_management_client.service.deleteAttachmentFromTestRecord( + self.uri, record_index, filename + ) - def delete_attachment_from_test_step(self, test_case_id, test_step_index, - filename): + def delete_attachment_from_test_step(self, test_case_id, test_step_index, filename): """Deletes Test Step Attachment of the specified step in the specified test record. @@ -934,9 +1006,9 @@ def delete_attachment_from_test_step(self, test_case_id, test_step_index, """ record_index = self._get_index_of_test_record(test_case_id) self._verify_test_step_count(record_index, test_step_index) - self.session.test_management_client.service. \ - deleteAttachmentFromTestStep(self.uri, record_index, - test_step_index, filename) + self.session.test_management_client.service.deleteAttachmentFromTestStep( + self.uri, record_index, test_step_index, filename + ) def delete_attachment(self, filename): """Deletes Test Run Attachment specified by attachment's @@ -952,8 +1024,9 @@ def delete_attachment(self, filename): test_management.deleteTestRunAttachment """ self._verify_obj() - self.session.test_management_client.service. \ - deleteTestRunAttachment(self.uri, filename) + self.session.test_management_client.service.deleteTestRunAttachment( + self.uri, filename + ) def get_attachment(self, filename): """Gets Test Run Attachment specified by attachment's @@ -969,8 +1042,9 @@ def get_attachment(self, filename): test_management.getTestRunAttachment """ self._verify_obj() - suds_attach = self.session.test_management_client.service. \ - getTestRunAttachment(self.uri, filename) + suds_attach = self.session.test_management_client.service.getTestRunAttachment( + self.uri, filename + ) return TestRunAttachment(suds_object=suds_attach) def get_attachments(self): @@ -986,10 +1060,13 @@ def get_attachments(self): test_management.getTestRunAttachments """ self._verify_obj() - lst_suds_attach = self.session.test_management_client.service. \ - getTestRunAttachments(self.uri) - lst_attach = [TestRunAttachment(suds_object=suds_attach) - for suds_attach in lst_suds_attach] + lst_suds_attach = ( + self.session.test_management_client.service.getTestRunAttachments(self.uri) + ) + lst_attach = [ + TestRunAttachment(suds_object=suds_attach) + for suds_attach in lst_suds_attach + ] return lst_attach def get_custom_field(self, field_name): @@ -1026,8 +1103,11 @@ def get_wiki_content(self): test_management.getWikiContentForTestRun """ self._verify_obj() - suds_wiki = self.session.test_management_client.service. \ - getWikiContentForTestRun(self.uri) + suds_wiki = ( + self.session.test_management_client.service.getWikiContentForTestRun( + self.uri + ) + ) return Text(suds_object=suds_wiki) def _set_custom_field(self, field_name, value): @@ -1077,8 +1157,7 @@ def update(self): for field in self._changed_fields: self._set_custom_field(field, self._changed_fields[field]) self._changed_fields = {} - self.session.test_management_client.service.updateTestRun( - self._suds_object) + self.session.test_management_client.service.updateTestRun(self._suds_object) def update_attachment(self, path, original_filename, title): """method update_attachment updates the specified attachment to the @@ -1102,11 +1181,13 @@ def update_attachment(self, path, original_filename, title): self._verify_obj() data = self._get_file_data(path) filename = os.path.basename(original_filename) - self.session.test_management_client.service. \ - updateTestRunAttachment(self.uri, filename, title, data) + self.session.test_management_client.service.updateTestRunAttachment( + self.uri, filename, title, data + ) - def update_summary_defect(self, source, total_failures, total_errors, - total_tests, defect_template_id): + def update_summary_defect( + self, source, total_failures, total_errors, total_tests, defect_template_id + ): """method update-summary_defect creates or updates the summary defect Work Item of a test run. @@ -1130,22 +1211,31 @@ def update_summary_defect(self, source, total_failures, total_errors, test_management.updateSummaryDefect """ self._verify_obj() - suds_defect_template = _WorkItem(work_item_id=defect_template_id, - project_id=self.project_id) + suds_defect_template = _WorkItem( + work_item_id=defect_template_id, project_id=self.project_id + ) defect_template_uri = suds_defect_template._uri - wi_uri = self.session.test_management_client.service. \ - updateSummaryDefect(self.uri, source, total_failures, total_errors, - total_tests, defect_template_uri) + wi_uri = self.session.test_management_client.service.updateSummaryDefect( + self.uri, + source, + total_failures, + total_errors, + total_tests, + defect_template_uri, + ) return _WorkItem(uri=wi_uri) @tx_wrapper - def update_test_record_by_fields(self, test_case_id, - test_result, - test_comment, - executed_by, - executed, - duration, - defect_work_item_id=None): + def update_test_record_by_fields( + self, + test_case_id, + test_result, + test_comment, + executed_by, + executed, + duration, + defect_work_item_id=None, + ): """method update_test_record_by_fields updates a test record. Args: @@ -1185,10 +1275,9 @@ def update_test_record_by_fields(self, test_case_id, self.update_test_record_by_object(test_case_id, testrec) @tx_wrapper - def update_test_record_by_object(self, - test_case_id, - test_record, - manual_state_change=False): + def update_test_record_by_object( + self, test_case_id, test_record, manual_state_change=False + ): """method update_test_record_by_object, adds a test record for the given test case based on the TestRecord object passed in. In addition, the test run is checked for completeness and the @@ -1216,18 +1305,18 @@ def update_test_record_by_object(self, if test_case_id not in test_case_ids: self.add_test_record_by_object(test_record) else: - if test_record.result == "failed" and \ - not test_record.defect_case_id: - test_record.defect_case_id = \ - create_incident_report(self, test_record, - TestCase(work_item_id=test_case_id)) + if test_record.result == "failed" and not test_record.defect_case_id: + test_record.defect_case_id = create_incident_report( + self, test_record, TestCase(work_item_id=test_case_id) + ) index = test_case_ids.index(test_case_id) if isinstance(test_record, TestRecord): suds_object = test_record._suds_object elif isinstance(test_record, TestRecord()._suds_object.__class__): suds_object = test_record - self.session.test_management_client.service. \ - updateTestRecordAtIndex(self.uri, index, suds_object) + self.session.test_management_client.service.updateTestRecordAtIndex( + self.uri, index, suds_object + ) if manual_state_change: self.update() else: @@ -1256,8 +1345,9 @@ def update_wiki_content(self, content): suds_content = content else: suds_content = suds.null() - self.session.test_management_client.service. \ - updateWikiContentForTestRun(self.uri, suds_content) + self.session.test_management_client.service.updateWikiContentForTestRun( + self.uri, suds_content + ) def verify_required(self): """function that checks if all required fields are passed in @@ -1270,8 +1360,9 @@ def verify_required(self): if not getattr(self, req): fields += (", " if fields else "") + req if fields: - raise PyleroLibException("These parameters are required: {0}". - format(fields)) + raise PyleroLibException( + "These parameters are required: {0}".format(fields) + ) def verify_params(self, **kwargs): """function that checks if all the kwargs are valid attributes. @@ -1289,5 +1380,4 @@ def verify_params(self, **kwargs): params += (", " if params else "") + param if params: - raise PyleroLibException("These parameters are unknown: {0}". - format(params)) + raise PyleroLibException("These parameters are unknown: {0}".format(params)) diff --git a/src/pylero/test_run_attachment.py b/src/pylero/test_run_attachment.py index 66184aa..0560502 100644 --- a/src/pylero/test_run_attachment.py +++ b/src/pylero/test_run_attachment.py @@ -19,20 +19,20 @@ class TestRunAttachment(BasePolarion): test_run_uri (SubterraURI) title (string) updated (dateTime) - url (string) -""" - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "filename": "fileName", - "id": "id", - "length": "length", - "title": "title", - "updated": "updated", - "url": "url", - "test_run_uri": "testRunURI", - "_uri": "_uri", - "_unresolvable": "_unresolvable"} + url (string)""" + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "filename": "fileName", + "id": "id", + "length": "length", + "title": "title", + "updated": "updated", + "url": "url", + "test_run_uri": "testRunURI", + "_uri": "_uri", + "_unresolvable": "_unresolvable", + } _obj_client = "test_management_client" _obj_struct = "tns4:TestRunAttachment" diff --git a/src/pylero/test_step.py b/src/pylero/test_step.py index 676a0ad..11f503a 100644 --- a/src/pylero/test_step.py +++ b/src/pylero/test_step.py @@ -13,15 +13,17 @@ class TestStep(BasePolarion): """Object to handle the Polarion WSDL tns3:TestStep class Attributes: - values (ArrayOfText) -""" + values (ArrayOfText)""" + _cls_suds_map = { - "values": - {"field_name": "values", - "is_array": True, - "cls": Text, - "arr_cls": ArrayOfText, - "inner_field_name": "Text"}} + "values": { + "field_name": "values", + "is_array": True, + "cls": Text, + "arr_cls": ArrayOfText, + "inner_field_name": "Text", + } + } _obj_client = "test_management_client" _obj_struct = "tns3:TestStep" diff --git a/src/pylero/test_step_result.py b/src/pylero/test_step_result.py index 6c628af..4b0141a 100644 --- a/src/pylero/test_step_result.py +++ b/src/pylero/test_step_result.py @@ -17,23 +17,25 @@ class TestStepResult(BasePolarion): Attributes: attachments (ArrayOfTestRunAttachment) comment (Text) - result (EnumOptionId) -""" - _cls_suds_map = {"attachments": - {"field_name": "attachments", - "is_array": True, - "cls": TestRunAttachment, - "arr_cls": ArrayOfTestRunAttachment, - "inner_field_name": "TestRunAttachment"}, - "comment": - {"field_name": "comment", - "cls": Text}, - "result": - {"field_name": "result", - "cls": EnumOptionId, - "enum_id": "testing/test-result"}, - "uri": "_uri", - "_unresolved": "_unresolved"} + result (EnumOptionId)""" + + _cls_suds_map = { + "attachments": { + "field_name": "attachments", + "is_array": True, + "cls": TestRunAttachment, + "arr_cls": ArrayOfTestRunAttachment, + "inner_field_name": "TestRunAttachment", + }, + "comment": {"field_name": "comment", "cls": Text}, + "result": { + "field_name": "result", + "cls": EnumOptionId, + "enum_id": "testing/test-result", + }, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "test_management_client" _obj_struct = "tns3:TestStepResult" diff --git a/src/pylero/test_steps.py b/src/pylero/test_steps.py index d8a7660..de6cdd5 100644 --- a/src/pylero/test_steps.py +++ b/src/pylero/test_steps.py @@ -16,22 +16,26 @@ class TestSteps(BasePolarion): Attributes: keys (ArrayOfEnumOptionId) - steps (ArrayOfTestStep) -""" - _cls_suds_map = {"keys": - {"field_name": "keys", - "is_array": True, - "cls": EnumOptionId, - "arr_cls": ArrayOfEnumOptionId, - "inner_field_name": "EnumOptionId", - "enum_id": "testing/test-step-keys"}, - "steps": - {"field_name": "steps", - "is_array": True, - "cls": TestStep, - "arr_cls": ArrayOfTestStep, - "inner_field_name": "TestStep"}, - "uri": "_uri", - "_unresolved": "_unresolved"} + steps (ArrayOfTestStep)""" + + _cls_suds_map = { + "keys": { + "field_name": "keys", + "is_array": True, + "cls": EnumOptionId, + "arr_cls": ArrayOfEnumOptionId, + "inner_field_name": "EnumOptionId", + "enum_id": "testing/test-step-keys", + }, + "steps": { + "field_name": "steps", + "is_array": True, + "cls": TestStep, + "arr_cls": ArrayOfTestStep, + "inner_field_name": "TestStep", + }, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "test_management_client" _obj_struct = "tns3:TestSteps" diff --git a/src/pylero/tests_configuration.py b/src/pylero/tests_configuration.py index b495767..78bb256 100644 --- a/src/pylero/tests_configuration.py +++ b/src/pylero/tests_configuration.py @@ -36,44 +36,45 @@ class TestsConfiguration(BasePolarion): test_case_test_comment_field_id (string) test_case_test_result_field_id (string) test_case_work_item_type (string) - test_run_template (string) -""" - _cls_suds_map = {"defect_auto_assignement_enabled": - "defectAutoAssignementEnabled", - "defect_reuse_type": "defectReuseType", - "defect_template": "defectTemplate", - "defect_to_test_case_link_role_id": - "defectToTestCaseLinkRoleId", - "defect_work_item_type": "defectWorkItemType", - "defects_project": "defectsProject", - "fields_to_copy_from_test_case_to_defect": - {"field_name": "fieldsToCopyFromTestCaseToDefect", - "cls": Properties}, - "fields_to_copy_from_test_run_to_linked_defect": - {"field_name": "fieldsToCopyFromTestRunToLinkedDefect", - "cls": Properties}, - "fields_to_copy_from_test_run_to_new_defect": - {"field_name": "fieldsToCopyFromTestRunToNewDefect", - "cls": Properties}, - "max_created_defects": "maxCreatedDefects", - "max_created_defects_percent": "maxCreatedDefectsPercent", - "result_error_enum_id": "resultErrorEnumId", - "result_failed_enum_id": "resultFailedEnumId", - "result_passed_enum_id": "resultPassedEnumId", - "retest_allowed": "retestAllowed", - "status_error_enum_id": "statusErrorEnumId", - "status_failed_enum_id": "statusFailedEnumId", - "status_ok_enum_id": "statusOkEnumId", - "summary_defect_severity": "summaryDefectSeverity", - "test_case_id_custom_field": "testCaseIdCustomField", - "test_case_template": "testCaseTemplate", - "test_case_test_comment_field_id": - "testCaseTestCommentFieldId", - "test_case_test_result_field_id": - "testCaseTestResultFieldId", - "test_case_work_item_type": "testCaseWorkItemType", - "test_run_template": "testRunTemplate", - "uri": "_uri", - "_unresolved": "_unresolved"} + test_run_template (string)""" + + _cls_suds_map = { + "defect_auto_assignement_enabled": "defectAutoAssignementEnabled", + "defect_reuse_type": "defectReuseType", + "defect_template": "defectTemplate", + "defect_to_test_case_link_role_id": "defectToTestCaseLinkRoleId", + "defect_work_item_type": "defectWorkItemType", + "defects_project": "defectsProject", + "fields_to_copy_from_test_case_to_defect": { + "field_name": "fieldsToCopyFromTestCaseToDefect", + "cls": Properties, + }, + "fields_to_copy_from_test_run_to_linked_defect": { + "field_name": "fieldsToCopyFromTestRunToLinkedDefect", + "cls": Properties, + }, + "fields_to_copy_from_test_run_to_new_defect": { + "field_name": "fieldsToCopyFromTestRunToNewDefect", + "cls": Properties, + }, + "max_created_defects": "maxCreatedDefects", + "max_created_defects_percent": "maxCreatedDefectsPercent", + "result_error_enum_id": "resultErrorEnumId", + "result_failed_enum_id": "resultFailedEnumId", + "result_passed_enum_id": "resultPassedEnumId", + "retest_allowed": "retestAllowed", + "status_error_enum_id": "statusErrorEnumId", + "status_failed_enum_id": "statusFailedEnumId", + "status_ok_enum_id": "statusOkEnumId", + "summary_defect_severity": "summaryDefectSeverity", + "test_case_id_custom_field": "testCaseIdCustomField", + "test_case_template": "testCaseTemplate", + "test_case_test_comment_field_id": "testCaseTestCommentFieldId", + "test_case_test_result_field_id": "testCaseTestResultFieldId", + "test_case_work_item_type": "testCaseWorkItemType", + "test_run_template": "testRunTemplate", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "test_management_client" _obj_struct = "tns3:TestsConfiguration" diff --git a/src/pylero/text.py b/src/pylero/text.py index adb0a1b..df219d7 100644 --- a/src/pylero/text.py +++ b/src/pylero/text.py @@ -18,9 +18,12 @@ class Text(BasePolarion): (eg. text/html) content_lossy (bool): """ - _cls_suds_map = {"content": "content", - "content_type": "type", - "content_lossy": "contentLossy"} + + _cls_suds_map = { + "content": "content", + "content_type": "type", + "content_lossy": "contentLossy", + } _id_field = "content" _obj_client = "test_management_client" _obj_struct = "tns2:Text" @@ -37,5 +40,6 @@ def _get_suds_object(self): class ArrayOfText(BasePolarion): """Object containing list of Text objects""" + _obj_client = "test_management_client" _obj_struct = "tns2:ArrayOfText" diff --git a/src/pylero/time_point.py b/src/pylero/time_point.py index 3ef8102..eb5a102 100644 --- a/src/pylero/time_point.py +++ b/src/pylero/time_point.py @@ -17,17 +17,17 @@ class TimePoint(BasePolarion): earliest_planned_start (date) time_point_id (string) name (string) - time (date) -""" - _cls_suds_map = {"closed": "closed", - "description": - {"field_name": "description", - "cls": Text}, - "earliest_planned_start": "earliestPlannedStart", - "time_point_id": "id", - "name": "name", - "time": "time", - "uri": "_uri", - "_unresolved": "_unresolved"} + time (date)""" + + _cls_suds_map = { + "closed": "closed", + "description": {"field_name": "description", "cls": Text}, + "earliest_planned_start": "earliestPlannedStart", + "time_point_id": "id", + "name": "name", + "time": "time", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:TimePoint" diff --git a/src/pylero/user.py b/src/pylero/user.py index 6c0a82a..64dac61 100644 --- a/src/pylero/user.py +++ b/src/pylero/user.py @@ -21,29 +21,31 @@ class User(BasePolarion): user_id (string) name (string) vote_uris (ArrayOfSubterraURI) - watche_uris (ArrayOfSubterraURI) -""" - _cls_suds_map = {"description": - {"field_name": "description", - "cls": Text}, - "disabled_notifications": "disabledNotifications", - "email": "email", - "user_id": "id", - "name": "name", - "vote_uris": - {"field_name": "voteURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "watche_uris": - {"field_name": "watcheURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "uri": "_uri", - "_unresolved": "_unresolved"} + watche_uris (ArrayOfSubterraURI)""" + + _cls_suds_map = { + "description": {"field_name": "description", "cls": Text}, + "disabled_notifications": "disabledNotifications", + "email": "email", + "user_id": "id", + "name": "name", + "vote_uris": { + "field_name": "voteURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "watche_uris": { + "field_name": "watcheURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "uri": "_uri", + "_unresolved": "_unresolved", + } _id_field = "user_id" _obj_client = "project_client" _obj_struct = "tns2:User" @@ -119,17 +121,16 @@ def __init__(self, user_id=None, suds_object=None, uri=None): Project.getUserByUri """ super(self.__class__, self).__init__(user_id, suds_object) -# user_id will be null if called from the get_users class function + # user_id will be null if called from the get_users class function if user_id or uri: if user_id: - self._suds_object = \ - self.session.project_client.service.getUser(user_id) + self._suds_object = self.session.project_client.service.getUser(user_id) elif uri: - self._suds_object = self.session.project_client.service. \ - getUserByUri(uri) + self._suds_object = self.session.project_client.service.getUserByUri( + uri + ) if getattr(self._suds_object, "_unresolvable", True): - raise PyleroLibException( - "The user {0} was not found.".format(user_id)) + raise PyleroLibException("The user {0} was not found.".format(user_id)) def get_context_roles(self, location): """Returns the context (project) roles for the user at given location. @@ -145,7 +146,8 @@ def get_context_roles(self, location): """ self._verify_obj() return self.session.security_client.service.getContextRolesForUser( - self.user_id, location) + self.user_id, location + ) def get_roles(self, location): """Returns all global and context roles for the context at given @@ -162,9 +164,10 @@ def get_roles(self, location): """ self._verify_obj() return self.session.security_client.service.getRolesForUser( - self.user_id, location) + self.user_id, location + ) -# getUserAvatarURL parameter is misnamed in the docs. it really takes user id. + # getUserAvatarURL parameter is misnamed in the docs. it really takes user id. def get_user_avatar_url(self): """method get_user_avatar_url, returns a string with the relative URL of the user's avatar. @@ -179,8 +182,7 @@ def get_user_avatar_url(self): Project.getUserAvatarURL """ if self.user_id: - return self.session.project_client.service.getUserAvatarURL( - self.user_id) + return self.session.project_client.service.getUserAvatarURL(self.user_id) else: raise PyleroLibException("The user object is empty") @@ -199,9 +201,9 @@ def has_permission(self, permission, project_id): Security.hasPermission """ self._verify_obj() - return self.session.security_client.service.hasPermission(self.user_id, - permission, - project_id) + return self.session.security_client.service.hasPermission( + self.user_id, permission, project_id + ) def update(self): """method update, updates Polarion with the User attributes diff --git a/src/pylero/wiki_page.py b/src/pylero/wiki_page.py index 0654dd6..862704b 100644 --- a/src/pylero/wiki_page.py +++ b/src/pylero/wiki_page.py @@ -32,43 +32,39 @@ class WikiPage(BasePolarion): title (string) type (string) updated (dateTime) - updated_by (User) -""" - _cls_suds_map = {"attachments": - {"field_name": "attachments", - "is_array": True, - "cls": WikiPageAttachment, - "arr_cls": ArrayOfWikiPageAttachment, - "inner_field_name": "WikiPageAttachment"}, - "author": - {"field_name": "author", - "cls": User}, - "created": "created", - "home_page_content": - {"field_name": "homePageContent", - "cls": Text}, - "wiki_page_id": "id", - "linked_page_uris": - {"field_name": "linkedPageURIs", - "is_array": True, - "cls": SubterraURI, - "arr_cls": ArrayOfSubterraURI, - "inner_field_name": "SubterraURI"}, - "location": "location", - "page_location": "pageLocation", - "page_name": "pageName", - "project": - {"field_name": "project", - "cls": Project}, - "space_id": "spaceId", - "title": "title", - "type": "type", - "updated": "updated", - "updated_by": - {"field_name": "updatedBy", - "cls": User}, - "uri": "_uri", - "_unresolved": "_unresolved"} + updated_by (User)""" + + _cls_suds_map = { + "attachments": { + "field_name": "attachments", + "is_array": True, + "cls": WikiPageAttachment, + "arr_cls": ArrayOfWikiPageAttachment, + "inner_field_name": "WikiPageAttachment", + }, + "author": {"field_name": "author", "cls": User}, + "created": "created", + "home_page_content": {"field_name": "homePageContent", "cls": Text}, + "wiki_page_id": "id", + "linked_page_uris": { + "field_name": "linkedPageURIs", + "is_array": True, + "cls": SubterraURI, + "arr_cls": ArrayOfSubterraURI, + "inner_field_name": "SubterraURI", + }, + "location": "location", + "page_location": "pageLocation", + "page_name": "pageName", + "project": {"field_name": "project", "cls": Project}, + "space_id": "spaceId", + "title": "title", + "type": "type", + "updated": "updated", + "updated_by": {"field_name": "updatedBy", "cls": User}, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:WikiPage" @@ -89,15 +85,23 @@ def get_wiki_pages(cls, project_id, space_id, fields): function_name += "WithFields" parms += [cls._convert_obj_fields_to_polarion(fields)] wikis = [] - for suds_wiki in getattr(cls.session.tracker_client.service, - function_name)(*parms): + for suds_wiki in getattr(cls.session.tracker_client.service, function_name)( + *parms + ): wikis.append(cls(suds_object=suds_wiki)) return wikis @classmethod - def query(cls, query, is_sql=False, fields=["wiki_page_id"], - sort="wiki_page_id", limit=-1, baseline_revision=None, - query_uris=False): + def query( + cls, + query, + is_sql=False, + fields=["wiki_page_id"], + sort="wiki_page_id", + limit=-1, + baseline_revision=None, + query_uris=False, + ): """Searches for Wiki Pages . Args: @@ -162,15 +166,15 @@ def query(cls, query, is_sql=False, fields=["wiki_page_id"], def __init__(self, fields=None, uri=None, suds_object=None): """ - Args: - fields: list of object fields to be returned in the object + Args: + fields: list of object fields to be returned in the object - Returns: - None + Returns: + None - References: - Tracker.getWikiPageByUri - tracker.getWikiPageByUriWithFields + References: + Tracker.getWikiPageByUri + tracker.getWikiPageByUriWithFields """ super(self.__class__, self).__init__(suds_object=suds_object) if uri: @@ -179,5 +183,6 @@ def __init__(self, fields=None, uri=None, suds_object=None): if fields: function_name += "WithFields" parms += [self._convert_obj_fields_to_polarion(fields)] - self._suds_object = getattr(self.session.tracker_client.service, - function_name)(*parms) + self._suds_object = getattr( + self.session.tracker_client.service, function_name + )(*parms) diff --git a/src/pylero/wiki_page_attachment.py b/src/pylero/wiki_page_attachment.py index 1e43ee2..4a90bb6 100644 --- a/src/pylero/wiki_page_attachment.py +++ b/src/pylero/wiki_page_attachment.py @@ -18,19 +18,19 @@ class WikiPageAttachment(BasePolarion): length (long) title (string) updated (dateTime) - url (string) -""" - _cls_suds_map = {"author": - {"field_name": "author", - "cls": User}, - "file_name": "fileName", - "wiki_page_attachment_id": "id", - "length": "length", - "title": "title", - "updated": "updated", - "url": "url", - "uri": "_uri", - "_unresolved": "_unresolved"} + url (string)""" + + _cls_suds_map = { + "author": {"field_name": "author", "cls": User}, + "file_name": "fileName", + "wiki_page_attachment_id": "id", + "length": "length", + "title": "title", + "updated": "updated", + "url": "url", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:WikiPageAttachment" diff --git a/src/pylero/work_item.py b/src/pylero/work_item.py index 6f09d43..6ebaaac 100644 --- a/src/pylero/work_item.py +++ b/src/pylero/work_item.py @@ -29,8 +29,7 @@ from pylero.enum_option_id import ArrayOfEnumOptionId # NOQA from pylero.enum_option_id import EnumOptionId from pylero.exceptions import PyleroLibException -from pylero.externally_linked_work_item \ - import ArrayOfExternallyLinkedWorkItem +from pylero.externally_linked_work_item import ArrayOfExternallyLinkedWorkItem from pylero.externally_linked_work_item import ExternallyLinkedWorkItem from pylero.hyperlink import ArrayOfHyperlink from pylero.hyperlink import Hyperlink @@ -52,6 +51,7 @@ from pylero.work_record import ArrayOfWorkRecord from pylero.work_record import WorkRecord from pylero.workflow_action import WorkflowAction + # ArrayOfEnumOptionId is used in dynamic code for custom fields @@ -98,157 +98,160 @@ class _WorkItem(BasePolarion): type (EnumOptionId) updated (dateTime) work_item_id (string) - work_records (ArrayOfWorkRecord) -""" + work_records (ArrayOfWorkRecord)""" + _cls_suds_map = { - "approvals": - {"field_name": "approvals", - "is_array": True, - "cls": Approval, - "arr_cls": ArrayOfApproval, - "inner_field_name": "Approval"}, - "assignee": - {"field_name": "assignee", - "is_array": True, - "cls": User, - "arr_cls": ArrayOfUser, - "inner_field_name": "User"}, - "attachments": - {"field_name": "attachments", - "is_array": True, - "cls": Attachment, - "arr_cls": ArrayOfAttachment, - "inner_field_name": "Attachment"}, - "author": - {"field_name": "author", - "cls": User}, + "approvals": { + "field_name": "approvals", + "is_array": True, + "cls": Approval, + "arr_cls": ArrayOfApproval, + "inner_field_name": "Approval", + }, + "assignee": { + "field_name": "assignee", + "is_array": True, + "cls": User, + "arr_cls": ArrayOfUser, + "inner_field_name": "User", + }, + "attachments": { + "field_name": "attachments", + "is_array": True, + "cls": Attachment, + "arr_cls": ArrayOfAttachment, + "inner_field_name": "Attachment", + }, + "author": {"field_name": "author", "cls": User}, "auto_suspect": "autoSuspect", - "categories": - {"field_name": "categories", - "is_array": True, - "cls": Category, - "arr_cls": ArrayOfCategory, - "inner_field_name": "Category"}, - "comments": - {"field_name": "comments", - "is_array": True, - "cls": Comment, - "arr_cls": ArrayOfComment, - "inner_field_name": "Comment"}, + "categories": { + "field_name": "categories", + "is_array": True, + "cls": Category, + "arr_cls": ArrayOfCategory, + "inner_field_name": "Category", + }, + "comments": { + "field_name": "comments", + "is_array": True, + "cls": Comment, + "arr_cls": ArrayOfComment, + "inner_field_name": "Comment", + }, "created": "created", # the custom field attribute has been changed to be a protected attr. # All interaction with custom fields should be done directly with the # derived attribute. - "_custom_fields": - {"field_name": "customFields", - "is_array": True, - "cls": Custom, - "arr_cls": ArrayOfCustom, - "inner_field_name": "Custom"}, - "description": - {"field_name": "description", - "cls": Text}, + "_custom_fields": { + "field_name": "customFields", + "is_array": True, + "cls": Custom, + "arr_cls": ArrayOfCustom, + "inner_field_name": "Custom", + }, + "description": {"field_name": "description", "cls": Text}, "due_date": "dueDate", - "externally_linked_work_items": - {"field_name": "externallyLinkedWorkItems", - "is_array": True, - "cls": ExternallyLinkedWorkItem, - "arr_cls": ArrayOfExternallyLinkedWorkItem, - "inner_field_name": "ExternallyLinkedWorkItem"}, - "hyperlinks": - {"field_name": "hyperlinks", - "is_array": True, - "cls": Hyperlink, - "arr_cls": ArrayOfHyperlink, - "inner_field_name": "Hyperlink"}, + "externally_linked_work_items": { + "field_name": "externallyLinkedWorkItems", + "is_array": True, + "cls": ExternallyLinkedWorkItem, + "arr_cls": ArrayOfExternallyLinkedWorkItem, + "inner_field_name": "ExternallyLinkedWorkItem", + }, + "hyperlinks": { + "field_name": "hyperlinks", + "is_array": True, + "cls": Hyperlink, + "arr_cls": ArrayOfHyperlink, + "inner_field_name": "Hyperlink", + }, "initial_estimate": "initialEstimate", - "linked_revisions": - {"field_name": "linkedRevisions", - "is_array": True, - "cls": Revision, - "arr_cls": ArrayOfRevision, - "inner_field_name": "Revision"}, - "linked_revisions_derived": - {"field_name": "linkedRevisionsDerived", - "is_array": True, - "cls": Revision, - "arr_cls": ArrayOfRevision, - "inner_field_name": "Revision"}, - "linked_work_items": - {"field_name": "linkedWorkItems", - "is_array": True, - "cls": LinkedWorkItem, - "arr_cls": ArrayOfLinkedWorkItem, - "inner_field_name": "LinkedWorkItem"}, - "linked_work_items_derived": - {"field_name": "linkedWorkItemsDerived", - "is_array": True, - "cls": LinkedWorkItem, - "arr_cls": ArrayOfLinkedWorkItem, - "inner_field_name": "LinkedWorkItem"}, + "linked_revisions": { + "field_name": "linkedRevisions", + "is_array": True, + "cls": Revision, + "arr_cls": ArrayOfRevision, + "inner_field_name": "Revision", + }, + "linked_revisions_derived": { + "field_name": "linkedRevisionsDerived", + "is_array": True, + "cls": Revision, + "arr_cls": ArrayOfRevision, + "inner_field_name": "Revision", + }, + "linked_work_items": { + "field_name": "linkedWorkItems", + "is_array": True, + "cls": LinkedWorkItem, + "arr_cls": ArrayOfLinkedWorkItem, + "inner_field_name": "LinkedWorkItem", + }, + "linked_work_items_derived": { + "field_name": "linkedWorkItemsDerived", + "is_array": True, + "cls": LinkedWorkItem, + "arr_cls": ArrayOfLinkedWorkItem, + "inner_field_name": "LinkedWorkItem", + }, "location": "location", - "module_uri": - {"field_name": "moduleURI", - "cls": SubterraURI}, + "module_uri": {"field_name": "moduleURI", "cls": SubterraURI}, "outline_number": "outlineNumber", "planned_end": "plannedEnd", # planned_in completed in the _fix_circular_refs func - "planned_in": - {"field_name": "plannedInURIs"}, + "planned_in": {"field_name": "plannedInURIs"}, "planned_start": "plannedStart", - "planning_constraints": - {"field_name": "planningConstraints", - "is_array": True, - "cls": PlanningConstraint, - "arr_cls": ArrayOfPlanningConstraint, - "inner_field_name": "PlanningConstraint"}, - "previous_status": - {"field_name": "previousStatus", - "cls": EnumOptionId, - "enum_id": "status"}, + "planning_constraints": { + "field_name": "planningConstraints", + "is_array": True, + "cls": PlanningConstraint, + "arr_cls": ArrayOfPlanningConstraint, + "inner_field_name": "PlanningConstraint", + }, + "previous_status": { + "field_name": "previousStatus", + "cls": EnumOptionId, + "enum_id": "status", + }, # priority is technically an enum, but it also accepts other values, # so we didn't include it here. If you want to enforce the enum in # the code, add "enum_id": "priority" to the prioirity dict - "priority": - {"field_name": "priority", - "cls": PriorityOptionId}, - "project_id": - {"field_name": "project", - "cls": Project}, + "priority": {"field_name": "priority", "cls": PriorityOptionId}, + "project_id": {"field_name": "project", "cls": Project}, "remaining_estimate": "remainingEstimate", - "resolution": - {"field_name": "resolution", - "cls": EnumOptionId, - "enum_id": "resolution"}, + "resolution": { + "field_name": "resolution", + "cls": EnumOptionId, + "enum_id": "resolution", + }, "resolved_on": "resolvedOn", - "severity": - {"field_name": "severity", - "cls": EnumOptionId, - "enum_id": "severity"}, - "status": - {"field_name": "status", - "cls": EnumOptionId, - "enum_id": "status"}, - "time_point": - {"field_name": "timePoint", - "cls": TimePoint}, + "severity": { + "field_name": "severity", + "cls": EnumOptionId, + "enum_id": "severity", + }, + "status": {"field_name": "status", "cls": EnumOptionId, "enum_id": "status"}, + "time_point": {"field_name": "timePoint", "cls": TimePoint}, "time_spent": "timeSpent", "title": "title", - "type": - {"field_name": "type", - "cls": EnumOptionId, - "enum_id": "workitem-type", - "enum_override": ["heading"]}, + "type": { + "field_name": "type", + "cls": EnumOptionId, + "enum_id": "workitem-type", + "enum_override": ["heading"], + }, "updated": "updated", "work_item_id": "id", - "work_records": - {"field_name": "workRecords", - "is_array": True, - "cls": WorkRecord, - "arr_cls": ArrayOfWorkRecord, - "inner_field_name": "WorkRecord"}, + "work_records": { + "field_name": "workRecords", + "is_array": True, + "cls": WorkRecord, + "arr_cls": ArrayOfWorkRecord, + "inner_field_name": "WorkRecord", + }, "uri": "_uri", - "_unresolved": "_unresolved"} + "_unresolved": "_unresolved", + } _id_field = "work_item_id" _obj_client = "tracker_client" _obj_struct = "tns3:WorkItem" @@ -287,8 +290,7 @@ def create(cls, project_id, wi_type, title, desc, status, **kwargs): wi.status = status for field in kwargs: setattr(wi, field, kwargs[field]) - wi_uri = cls.session.tracker_client.service.createWorkItem( - wi._suds_object) + wi_uri = cls.session.tracker_client.service.createWorkItem(wi._suds_object) new_wi = cls(uri=wi_uri) return new_wi @@ -325,22 +327,31 @@ def get_defined_custom_field_types(cls, project_id, wi_type): tracker.getDefinedCustomFieldTypes """ if not cls._cache["custom_field_types"].get(wi_type): - cfts = cls.session.tracker_client.service. \ - getDefinedCustomFieldTypes(project_id, wi_type) + cfts = cls.session.tracker_client.service.getDefinedCustomFieldTypes( + project_id, wi_type + ) cls._cache["custom_field_types"][wi_type] = cfts else: cfts = cls._cache["custom_field_types"].get(wi_type) - results = [CustomFieldType(suds_object=item) - if isinstance(item, - CustomFieldType()._suds_object.__class__) - else EnumCustomFieldType(suds_object=item) - for item in cfts] + results = [ + CustomFieldType(suds_object=item) + if isinstance(item, CustomFieldType()._suds_object.__class__) + else EnumCustomFieldType(suds_object=item) + for item in cfts + ] return results @classmethod - def query(cls, query, is_sql=False, fields=["work_item_id"], - sort="work_item_id", limit=-1, baseline_revision=None, - query_uris=False): + def query( + cls, + query, + is_sql=False, + fields=["work_item_id"], + sort="work_item_id", + limit=-1, + baseline_revision=None, + query_uris=False, + ): """Searches for Work Items. Notes: @@ -428,8 +439,15 @@ def query(cls, query, is_sql=False, fields=["work_item_id"], lst_wi = [cls(suds_object=wi) for wi in wis] return lst_wi - def __init__(self, project_id=None, work_item_id=None, suds_object=None, - uri=None, fields=None, revision=None): + def __init__( + self, + project_id=None, + work_item_id=None, + suds_object=None, + uri=None, + fields=None, + revision=None, + ): """WorkItem constructor. Args: @@ -470,19 +488,26 @@ def __init__(self, project_id=None, work_item_id=None, suds_object=None, parms = [] if work_item_id: function_name += "Id" if not p_fields else "IdsWithFields" - parms = [project_id, work_item_id] + \ - ([p_fields] if p_fields else []) + parms = [project_id, work_item_id] + ([p_fields] if p_fields else []) elif uri: - function_name += "Uri" + ("InRevision" if revision else "") + \ - ("WithFields" if p_fields else "") - parms = [uri] + ([revision] if revision else []) + \ - ([p_fields] if p_fields else []) - self._suds_object = getattr(self.session.tracker_client.service, - function_name)(*parms) + function_name += ( + "Uri" + + ("InRevision" if revision else "") + + ("WithFields" if p_fields else "") + ) + parms = ( + [uri] + + ([revision] if revision else []) + + ([p_fields] if p_fields else []) + ) + self._suds_object = getattr( + self.session.tracker_client.service, function_name + )(*parms) if not suds_object: if getattr(self._suds_object, "_unresolvable", True): raise PyleroLibException( - "The WorkItem {0} was not found.".format(work_item_id)) + "The WorkItem {0} was not found.".format(work_item_id) + ) # if it is a suds object, only relevant fields are passed in. if not self.project_id and not suds_object: self.project_id = self.default_project @@ -493,6 +518,7 @@ def _fix_circular_refs(self): # allowed, so the self reference is defined here. from pylero.plan import Plan from pylero.plan import ArrayOfPlan + self._cls_suds_map["planned_in"]["is_array"] = True self._cls_suds_map["planned_in"]["cls"] = Plan self._cls_suds_map["planned_in"]["arr_cls"] = ArrayOfPlan @@ -516,8 +542,7 @@ def add_approvee(self, approvee_id): allowed = self.get_allowed_approvers() allowed_ids = [u.user_id for u in allowed] if approvee_id not in (allowed_ids): - raise PyleroLibException("%s is not an allowed assignee" % - approvee_id) + raise PyleroLibException("%s is not an allowed assignee" % approvee_id) self.session.tracker_client.service.addApprovee(self.uri, approvee_id) def add_assignee(self, assignee_id): @@ -537,33 +562,29 @@ def add_assignee(self, assignee_id): allowed = self.get_allowed_assignees() allowed_ids = [u.user_id for u in allowed] if assignee_id not in (allowed_ids): - raise PyleroLibException("%s is not an allowed assignee" % - assignee_id) - return self.session.tracker_client.service.addAssignee(self.uri, - assignee_id) + raise PyleroLibException("%s is not an allowed assignee" % assignee_id) + return self.session.tracker_client.service.addAssignee(self.uri, assignee_id) def add_category(self, category_id): """method add_category adds a category to the current _WorkItem - The category passed in must be a defined category in the current project + The category passed in must be a defined category in the current project - Args: - category_id (str): id of the category to add + Args: + category_id (str): id of the category to add - Returns: - bool + Returns: + bool - References: - Tracker.addCategoy + References: + Tracker.addCategoy """ self._verify_obj() proj = Project(self.project_id) cats = proj.get_categories() cat_ids = [cat.category_id for cat in cats] if category_id not in cat_ids: - raise PyleroLibException("the category_id must be one of: %s" % - cat_ids) - return self.session.tracker_client.service.addCategory(self.uri, - category_id) + raise PyleroLibException("the category_id must be one of: %s" % cat_ids) + return self.session.tracker_client.service.addCategory(self.uri, category_id) def add_external_linked_revision(self, repository_name, revision_id): """method add_external_linked_revision links a revision from external @@ -581,7 +602,8 @@ def add_external_linked_revision(self, repository_name, revision_id): """ self._verify_obj() return self.session.tracker_client.service.addExternalLinkedRevision( - self.uri, repository_name, revision_id) + self.uri, repository_name, revision_id + ) def add_hyperlink(self, url, role): """method add_hyperlink adds a hyperlink to a _WorkItem @@ -600,10 +622,10 @@ def add_hyperlink(self, url, role): self.check_valid_field_values(role, "hyperlink-role", {}) suds_role = EnumOptionId(role)._suds_object return self.session.tracker_client.service.addHyperlink( - self.uri, url, suds_role) + self.uri, url, suds_role + ) - def add_linked_item(self, linked_work_item_id, role, - revision=None, suspect=None): + def add_linked_item(self, linked_work_item_id, role, revision=None, suspect=None): """method add_linked_item adds a linked _WorkItem to current _WorkItem The linking is done to the "child" object. For example, if you have a Test Case that verifies a requirement, you would add the @@ -631,16 +653,16 @@ def add_linked_item(self, linked_work_item_id, role, self._verify_obj() # validates the role. Will raise PyleroLibException if invalid self.check_valid_field_values(role, "workitem-link-role", {}) - wi_linked = _WorkItem(work_item_id=linked_work_item_id, - project_id=self.project_id) + wi_linked = _WorkItem( + work_item_id=linked_work_item_id, project_id=self.project_id + ) enum_role = EnumOptionId(role)._suds_object function_name = "addLinkedItem" parms = [self.uri, wi_linked.uri, enum_role] if revision: function_name += "WithRev" parms += [revision, suspect] - return getattr(self.session.tracker_client.service, - function_name)(*parms) + return getattr(self.session.tracker_client.service, function_name)(*parms) def add_linked_revision(self, revision): """method add_linked_revision links a revision to the current _WorkItem @@ -655,8 +677,7 @@ def add_linked_revision(self, revision): Tracker.addLinkedRevision """ self._verify_obj() - return self.session.tracker_client.service.addLinkedRevision(self.uri, - revision) + return self.session.tracker_client.service.addLinkedRevision(self.uri, revision) def create_attachment(self, path, title): """method create_attachment adds the given attachment to the current @@ -675,8 +696,9 @@ def create_attachment(self, path, title): self._verify_obj() data = self._get_file_data(path) filename = os.path.basename(path) - self.session.tracker_client.service. \ - createAttachment(self.uri, filename, title, data) + self.session.tracker_client.service.createAttachment( + self.uri, filename, title, data + ) def create_comment(self, content): """method create_comment adds a comment to the current _WorkItem @@ -702,11 +724,11 @@ def create_comment(self, content): else: suds_content = suds.null() - self.session.tracker_client.service.createComment(self.uri, - suds_content) + self.session.tracker_client.service.createComment(self.uri, suds_content) - def create_work_record(self, user_id, date_worked, time_spent, - record_type=None, record_comment=None): + def create_work_record( + self, user_id, date_worked, time_spent, record_type=None, record_comment=None + ): """Creates a work record Args: @@ -752,8 +774,7 @@ def delete_attachment(self, attachment_id): Tracker.deleteAttachment """ self._verify_obj() - self.session.tracker_client.service.deleteAttachment( - self.uri, attachment_id) + self.session.tracker_client.service.deleteAttachment(self.uri, attachment_id) def do_auto_suspect(self): """Triggers auto suspect. @@ -804,7 +825,8 @@ def edit_approval(self, approvee_id, status): self.check_valid_field_values(status, "approval-status", {}) suds_status = EnumOptionId(status)._suds_object self.session.tracker_client.service.editApproval( - self.uri, approvee_id, suds_status) + self.uri, approvee_id, suds_status + ) def get_allowed_approvers(self): """Gets all allowed approvers" @@ -819,8 +841,9 @@ def get_allowed_approvers(self): Tracker.getAllowedApprovers """ users = [] - for suds_user in self.session.tracker_client.service. \ - getAllowedApprovers(self.uri): + for suds_user in self.session.tracker_client.service.getAllowedApprovers( + self.uri + ): users.append(User(suds_object=suds_user)) return users @@ -837,8 +860,9 @@ def get_allowed_assignees(self): Tracker.getAllowedAssignees """ users = [] - for suds_user in self.session.tracker_client.service. \ - getAllowedAssignees(self.uri): + for suds_user in self.session.tracker_client.service.getAllowedAssignees( + self.uri + ): users.append(User(suds_object=suds_user)) return users @@ -858,8 +882,9 @@ def get_available_actions(self): """ self._verify_obj() actions = [] - for suds_action in self.session.tracker_client.service. \ - getAvailableActions(self.uri): + for suds_action in self.session.tracker_client.service.getAvailableActions( + self.uri + ): actions.append(WorkflowAction(suds_object=suds_action)) return actions @@ -878,8 +903,9 @@ def get_back_linked_work_items(self): """ self._verify_obj() linked_work_items = [] - for suds_lwi in self.session.tracker_client.service. \ - getBackLinkedWorkitems(self.uri): + for suds_lwi in self.session.tracker_client.service.getBackLinkedWorkitems( + self.uri + ): linked_work_items.append(LinkedWorkItem(suds_object=suds_lwi)) return linked_work_items @@ -896,8 +922,7 @@ def get_custom_field(self, key): Tracker.getCustomField """ self._verify_obj() - suds_custom = self.session.tracker_client.service.getCustomField( - self.uri, key) + suds_custom = self.session.tracker_client.service.getCustomField(self.uri, key) return CustomField(suds_object=suds_custom) def get_custom_field_keys(self): @@ -931,7 +956,8 @@ def get_custom_field_type(self, key): """ self._verify_obj() suds_custom = self.session.tracker_client.service.getCustomFieldType( - self.uri, key) + self.uri, key + ) return CustomFieldType(suds_object=suds_custom) def get_custom_field_types(self): @@ -949,8 +975,9 @@ def get_custom_field_types(self): """ self._verify_obj() custom_types = [] - for suds_custom in self.session.tracker_client.service. \ - getCustomFieldTypes(self.uri): + for suds_custom in self.session.tracker_client.service.getCustomFieldTypes( + self.uri + ): custom_types.append(CustomFieldType(suds_object=suds_custom)) def get_enum_control_key_for_id(self, enum_id): @@ -966,7 +993,8 @@ def get_enum_control_key_for_id(self, enum_id): Tracker.getEnumControlKeyForId """ return self.session.tracker_client.service.getEnumControlKeyForId( - self.project_id, enum_id) + self.project_id, enum_id + ) def get_enum_control_key_for_key(self, key): """Gets the enumeration control key for the specified work item key. @@ -982,7 +1010,8 @@ def get_enum_control_key_for_key(self, key): Tracker.getEnumControlKeyForId """ return self.session.tracker_client.service.getEnumControlKeyForId( - self.project_id, key) + self.project_id, key + ) def get_initial_workflow_action(self, work_item_type=None): """Gets the initial workflow action for the specified object, returns @@ -1005,8 +1034,7 @@ def get_initial_workflow_action(self, work_item_type=None): if work_item_type: function_name += "ForProjectAndType" parm += [work_item_type] - suds_action = getattr(self.session.tracker_client.service, - function_name)(*parm) + suds_action = getattr(self.session.tracker_client.service, function_name)(*parm) return WorkflowAction(suds_object=suds_action) def get_test_steps(self): @@ -1022,8 +1050,7 @@ def get_test_steps(self): Tracker.getTestSteps """ self._verify_obj() - suds_ts = self.session.test_management_client.service. \ - getTestSteps(self.uri) + suds_ts = self.session.test_management_client.service.getTestSteps(self.uri) return TestSteps(suds_object=suds_ts) def get_unavailable_actions(self): @@ -1044,8 +1071,9 @@ def get_unavailable_actions(self): """ self._verify_obj() actions = [] - for suds_action in self.session.tracker_client.service. \ - getUnavailableActions(self.uri): + for suds_action in self.session.tracker_client.service.getUnavailableActions( + self.uri + ): actions.append(WorkflowAction(suds_object=suds_action)) return actions @@ -1063,8 +1091,7 @@ def perform_workflow_action(self, action_id): Tracker.performWorkflowAction """ self._verify_obj() - self.session.tracker_client.service.performWorkflowAction(self.uri, - action_id) + self.session.tracker_client.service.performWorkflowAction(self.uri, action_id) def remove_assignee(self, assignee_id): """removes an assignee from the _WorkItem. @@ -1079,8 +1106,7 @@ def remove_assignee(self, assignee_id): Tracker.removeAssignee """ self._verify_obj() - return self.session.tracker_client.service.removeAssignee(self.uri, - assignee_id) + return self.session.tracker_client.service.removeAssignee(self.uri, assignee_id) def remove_category(self, category_id): """removes a category from the _WorkItem. @@ -1095,8 +1121,7 @@ def remove_category(self, category_id): Tracker.removeCategory """ self._verify_obj() - return self.session.tracker_client.service.removeCategory(self.uri, - category_id) + return self.session.tracker_client.service.removeCategory(self.uri, category_id) def remove_external_linked_revision(self, repository_name, revision_id): """Removes a revision from external repository. @@ -1112,9 +1137,9 @@ def remove_external_linked_revision(self, repository_name, revision_id): Tracker.removeExternalLinkedRevision """ self._verify_obj() - return self.session.tracker_client.service. \ - removeExternalLinkedRevision(self.uri, repository_name, - revision_id) + return self.session.tracker_client.service.removeExternalLinkedRevision( + self.uri, repository_name, revision_id + ) def remove_externally_linked_item(self, linked_external_workitem_id, role): """Removes an externally linked work item. @@ -1131,8 +1156,9 @@ def remove_externally_linked_item(self, linked_external_workitem_id, role): """ self._verify_obj() external_wi = _WorkItem(uri=linked_external_workitem_id) - return self.session.tracker_client.service. \ - removeExternallyLinkedItem(self.uri, external_wi.uri, role) + return self.session.tracker_client.service.removeExternallyLinkedItem( + self.uri, external_wi.uri, role + ) def remove_hyperlink(self, url): """Removes a hyperlink from the _WorkItem @@ -1147,8 +1173,7 @@ def remove_hyperlink(self, url): Tracker.removeHyperlink """ self._verify_obj() - return self.session.tracker_client.service. \ - removeHyperlink(self.uri, url) + return self.session.tracker_client.service.removeHyperlink(self.uri, url) def remove_linked_item(self, linked_item_id, role): """Removes a linked work item. @@ -1164,11 +1189,11 @@ def remove_linked_item(self, linked_item_id, role): Tracker.removeLinkedItem """ self._verify_obj() - wi_linked = _WorkItem(work_item_id=linked_item_id, - project_id=self.project_id) + wi_linked = _WorkItem(work_item_id=linked_item_id, project_id=self.project_id) enum_role = EnumOptionId(role)._suds_object - return self.session.tracker_client.service. \ - removeLinkedItem(self.uri, wi_linked.uri, enum_role) + return self.session.tracker_client.service.removeLinkedItem( + self.uri, wi_linked.uri, enum_role + ) def remove_linked_revision(self, revision_id): """Removes a revision @@ -1183,8 +1208,9 @@ def remove_linked_revision(self, revision_id): Tracker.removeLinkedRevision """ self._verify_obj() - return self.session.tracker_client.service. \ - removeLinkedRevision(self.uri, revision_id) + return self.session.tracker_client.service.removeLinkedRevision( + self.uri, revision_id + ) def remove_planning_constraint(self, constraint_date, constraint): """Removes a planning constraint @@ -1200,8 +1226,9 @@ def remove_planning_constraint(self, constraint_date, constraint): Tracker.removePlaningConstraint """ self._verify_obj() - return self.session.tracker_client.service. \ - removePlaningConstraint(self.uri, constraint_date, constraint) + return self.session.tracker_client.service.removePlaningConstraint( + self.uri, constraint_date, constraint + ) def reset_workflow(self): """resets the workflow for the current object. Performs initial action @@ -1276,13 +1303,11 @@ def set_test_steps(self, test_steps=None): parm = [] if isinstance(test_steps[0], TestStep): parm = [item._suds_object for item in test_steps] - elif isinstance(test_steps[0], TestStep(). - _suds_object.__class__): + elif isinstance(test_steps[0], TestStep()._suds_object.__class__): parm = test_steps else: raise PyleroLibException("Expecting a list of testStep objects") - self.session.test_management_client.service.setTestSteps(self.uri, - parm) + self.session.test_management_client.service.setTestSteps(self.uri, parm) def update(self): """Update the server with the current _WorkItem data @@ -1320,14 +1345,14 @@ def update_attachment(self, attachment_id, path, title): self._verify_obj() data = self._get_file_data(path) filename = os.path.basename(path) - self.session.tracker_client.service. \ - updateAttachment(self.uri, attachment_id, filename, title, data) + self.session.tracker_client.service.updateAttachment( + self.uri, attachment_id, filename, title, data + ) def verify_required(self): for field in self._required_fields: if not getattr(self, field): - raise PyleroLibException( - "{0} is a required field".format(field)) + raise PyleroLibException("{0} is a required field".format(field)) def which_test_runs(self): """Gives the user a list of TestRun objects that the current WorkItem @@ -1341,6 +1366,7 @@ def which_test_runs(self): """ # import done in the function so as not to cause circular refs from pylero.test_run import TestRun + return TestRun.search(self.work_item_id) @@ -1349,6 +1375,7 @@ class _SpecificWorkItem(_WorkItem): that is different per WorkItem type. Classes that inherit from this class must define the _wi_type class attribute as a minimum. """ + _wi_type = "" _got_custom_fields = False _required_fields = [] @@ -1376,17 +1403,17 @@ def create(cls, project_id, title, desc, status="draft", **kwargs): if req not in kwargs: fields += (", " if fields else "") + req if fields: - raise PyleroLibException("These parameters are required: {0}". - format(fields)) + raise PyleroLibException( + "These parameters are required: {0}".format(fields) + ) for field in kwargs: - if field not in cls._all_custom_fields and \ - field not in cls._cls_suds_map: + if field not in cls._all_custom_fields and field not in cls._cls_suds_map: fields += (", " if fields else "") + field if fields: - raise PyleroLibException("These parameters are unknown: {0}". - format(fields)) + raise PyleroLibException("These parameters are unknown: {0}".format(fields)) return super(_SpecificWorkItem, cls).create( - project_id, cls._wi_type, title, desc, status, **kwargs) + project_id, cls._wi_type, title, desc, status, **kwargs + ) @classmethod def get_custom_fields(cls, project_id): @@ -1402,14 +1429,18 @@ def get_custom_fields(cls, project_id): """ cls._required_fields = [] cls._all_custom_fields = [] - cfts = cls.get_defined_custom_field_types(project_id, - cls._wi_type) + cfts = cls.get_defined_custom_field_types(project_id, cls._wi_type) for cft in cfts: # convert the custom field name to use code convention, where # possible - split_name = re.findall('[a-zA-Z][^A-Z]*', cft.cft_id) - local_name = "_".join(split_name).replace("_U_R_I", "_uri"). \ - replace("_W_I", "_wi").replace("_I_D", "_id").lower() + split_name = re.findall("[a-zA-Z][^A-Z]*", cft.cft_id) + local_name = ( + "_".join(split_name) + .replace("_U_R_I", "_uri") + .replace("_W_I", "_wi") + .replace("_I_D", "_id") + .lower() + ) cls._all_custom_fields.append(local_name) cls._cls_suds_map[local_name] = {} cls._cls_suds_map[local_name]["field_name"] = cft.cft_id @@ -1419,11 +1450,8 @@ def get_custom_fields(cls, project_id): # for all object types, I need special processing. parse_type = cft.type.split(":") if parse_type[0].startswith("ns"): - cls._cls_suds_map[local_name]["cls"] = \ - globals()[parse_type[1]] - cls._cls_suds_map[local_name]["enum_id"] = getattr(cft, - "enum_id", - None) + cls._cls_suds_map[local_name]["cls"] = globals()[parse_type[1]] + cls._cls_suds_map[local_name]["enum_id"] = getattr(cft, "enum_id", None) cls._cls_suds_map[local_name]["is_custom"] = True cls._cls_suds_map[local_name]["control"] = cls._wi_type if cft.multi: @@ -1434,9 +1462,16 @@ def get_custom_fields(cls, project_id): return None @classmethod - def query(cls, query, fields=["work_item_id"], - sort="work_item_id", limit=-1, baseline_revision=None, - query_uris=False, project_id=None): + def query( + cls, + query, + fields=["work_item_id"], + sort="work_item_id", + limit=-1, + baseline_revision=None, + query_uris=False, + project_id=None, + ): """Function overrides the query function in the _WorkItem class. It only accepts Lucene queries, specifically queries the specific type of work item and the default project. To search other projects, there is a @@ -1490,13 +1525,23 @@ def query(cls, query, fields=["work_item_id"], cls.get_custom_fields(project_id or cls.default_project) if query: query += " AND " - query += "type:%s AND project.id:%s" % \ - (cls._wi_type, project_id or cls.default_project) + query += "type:%s AND project.id:%s" % ( + cls._wi_type, + project_id or cls.default_project, + ) return super(_SpecificWorkItem, cls).query( - query, False, fields, sort, limit, baseline_revision, query_uris) - - def __init__(self, project_id=None, work_item_id=None, suds_object=None, - uri=None, fields=None, revision=None): + query, False, fields, sort, limit, baseline_revision, query_uris + ) + + def __init__( + self, + project_id=None, + work_item_id=None, + suds_object=None, + uri=None, + fields=None, + revision=None, + ): """In this constructor, it adds the custom fields per WorkItem type to the _cls_suds_map along with the is_custom and is_enum fields. In the property builder of the base class, it defines special behavior @@ -1506,14 +1551,15 @@ def __init__(self, project_id=None, work_item_id=None, suds_object=None, project_id = self.default_project self._changed_fields = {} self.get_custom_fields(project_id) - super(_SpecificWorkItem, self).__init__(project_id, work_item_id, - suds_object, uri, fields, - revision) + super(_SpecificWorkItem, self).__init__( + project_id, work_item_id, suds_object, uri, fields, revision + ) if not self.type: self.type = self._wi_type if self.type != self._wi_type: - raise PyleroLibException("This is of type {0}, not type {1}". - format(self.type, self._wi_type)) + raise PyleroLibException( + "This is of type {0}, not type {1}".format(self.type, self._wi_type) + ) @tx_wrapper def update(self): @@ -1539,10 +1585,13 @@ def update(self): workitems[item.id] = item.name.replace(" ", "") for wi in workitems: - newclass = type(str(workitems[wi]), - (_SpecificWorkItem,), - {"_wi_type": wi, - "_cls_suds_map": - copy.deepcopy(_SpecificWorkItem._cls_suds_map)}) + newclass = type( + str(workitems[wi]), + (_SpecificWorkItem,), + { + "_wi_type": wi, + "_cls_suds_map": copy.deepcopy(_SpecificWorkItem._cls_suds_map), + }, + ) # Add the class to the module's namespace globals()[str(workitems[wi])] = newclass diff --git a/src/pylero/work_record.py b/src/pylero/work_record.py index aa0bb43..a61dca2 100644 --- a/src/pylero/work_record.py +++ b/src/pylero/work_record.py @@ -18,21 +18,22 @@ class WorkRecord(BasePolarion): work_record_id (string) time_spent (duration) type (EnumOptionId) - user (User) -""" - _cls_suds_map = {"comment": "comment", - "date": "date", - "work_record_id": "id", - "time_spent": "timeSpent", - "type": - {"field_name": "type", - "cls": EnumOptionId, - "enum_id": "work-record-type"}, - "user": - {"field_name": "user", - "cls": User}, - "uri": "_uri", - "_unresolved": "_unresolved"} + user (User)""" + + _cls_suds_map = { + "comment": "comment", + "date": "date", + "work_record_id": "id", + "time_spent": "timeSpent", + "type": { + "field_name": "type", + "cls": EnumOptionId, + "enum_id": "work-record-type", + }, + "user": {"field_name": "user", "cls": User}, + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "builder_client" _obj_struct = "tns5:WorkRecord" diff --git a/src/pylero/workflow_action.py b/src/pylero/workflow_action.py index bd71a6c..26d28ee 100644 --- a/src/pylero/workflow_action.py +++ b/src/pylero/workflow_action.py @@ -19,19 +19,19 @@ class WorkflowAction(BasePolarion): required_features (ArrayOf_xsd_string) suggested_features (ArrayOf_xsd_string) target_status (EnumOptionId) - unavailability_message (string) -""" - _cls_suds_map = {"action_id": "actionId", - "action_name": "actionName", - "cleaned_features": "cleaned_features", - "native_action_id": "nativeActionId", - "required_features": "requiredFeatures", - "suggested_features": "suggestedFeatures", - "target_status": - {"field_name": "targetStatus", - "cls": EnumOptionId}, - "unavailability_message": "unavailabilityMessage", - "uri": "_uri", - "_unresolved": "_unresolved"} + unavailability_message (string)""" + + _cls_suds_map = { + "action_id": "actionId", + "action_name": "actionName", + "cleaned_features": "cleaned_features", + "native_action_id": "nativeActionId", + "required_features": "requiredFeatures", + "suggested_features": "suggestedFeatures", + "target_status": {"field_name": "targetStatus", "cls": EnumOptionId}, + "unavailability_message": "unavailabilityMessage", + "uri": "_uri", + "_unresolved": "_unresolved", + } _obj_client = "tracker_client" _obj_struct = "tns3:WorkflowAction" diff --git a/src/unit_tests/attribute_test.py b/src/unit_tests/attribute_test.py index 0aaf588..6507df7 100644 --- a/src/unit_tests/attribute_test.py +++ b/src/unit_tests/attribute_test.py @@ -5,8 +5,8 @@ from __future__ import unicode_literals import datetime - import unittest + from pylero.document import Document from pylero.exceptions import PyleroLibException from pylero.test_record import TestRecord @@ -31,15 +31,20 @@ class AttributeTest(unittest.TestCase): - @classmethod def setUpClass(cls): global TEST_RUN_ID cls.doc = Document.create( - DEFAULT_PROJ, "Testing", DOC_NAME, - "Attribute_Test", ["testcase"], "testspecification") + DEFAULT_PROJ, + "Testing", + DOC_NAME, + "Attribute_Test", + ["testcase"], + "testspecification", + ) cls.testrun = TestRun.create( - DEFAULT_PROJ, TEST_RUN_ID, "example", TEST_RUN_TITLE) + DEFAULT_PROJ, TEST_RUN_ID, "example", TEST_RUN_TITLE + ) TEST_RUN_ID = cls.testrun.test_run_id # arch is a custom field defined by global admins for test runs. # It is set here for a test on custom fields that requires at least two @@ -50,21 +55,22 @@ def setUpClass(cls): cls.testrun.arch = valid_values[1] cls.testrun.update() - cls.tc = TestCase.create(DEFAULT_PROJ, - "regression", - "regression", - caseimportance="high", - caselevel="component", - caseautomation="notautomated", - caseposneg="positive", - testtype="functional", - subtype1="-") + cls.tc = TestCase.create( + DEFAULT_PROJ, + "regression", + "regression", + caseimportance="high", + caselevel="component", + caseautomation="notautomated", + caseposneg="positive", + testtype="functional", + subtype1="-", + ) cls.TEST_CASE_ID = cls.tc.work_item_id @classmethod def tearDownClass(cls): - doc = Document(project_id=DEFAULT_PROJ, - doc_with_space="Testing/" + DOC_NAME) + doc = Document(project_id=DEFAULT_PROJ, doc_with_space="Testing/" + DOC_NAME) doc.delete() def test_basic(self): @@ -72,8 +78,7 @@ def test_basic(self): self.doc.title = "new title" self.assertEqual(self.doc.title, "new title") self.doc.update() - doc2 = Document(project_id=DEFAULT_PROJ, - doc_with_space="Testing/" + DOC_NAME) + doc2 = Document(project_id=DEFAULT_PROJ, doc_with_space="Testing/" + DOC_NAME) self.assertEqual(doc2.title, "new title") def test_obj_writeuser(self): @@ -96,8 +101,7 @@ def test_enum(self): self.assertEqual(self.doc.status, "obsolete") def test_arr_obj(self): - testrun = TestRun(project_id=DEFAULT_PROJ, - test_run_id=TEST_RUN_ID) + testrun = TestRun(project_id=DEFAULT_PROJ, test_run_id=TEST_RUN_ID) recs = testrun.records if not isinstance(recs, list): recs = [] @@ -112,14 +116,13 @@ def test_arr_obj(self): rec.result = "passed" recs.append(rec) testrun.records = recs - self.assertEqual(cnt+1, len(testrun.records)) + self.assertEqual(cnt + 1, len(testrun.records)) recs = testrun.records rec = recs[-1] self.assertEqual(rec.result, "passed") def test_custom_testrun(self): - testrun = TestRun(project_id=DEFAULT_PROJ, - test_run_id=TEST_RUN_ID) + testrun = TestRun(project_id=DEFAULT_PROJ, test_run_id=TEST_RUN_ID) self.assertIsNotNone(testrun.arch) with self.assertRaises(PyleroLibException): testrun.arch = "bad" @@ -144,8 +147,7 @@ def test_custom_testrun2(self): self.assertEqual(valid_values[0], testrun.arch) def test_custom_workitem(self): - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.TEST_CASE_ID) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.TEST_CASE_ID) self.assertIsNotNone(tc2.caseautomation) with self.assertRaises(PyleroLibException): tc2.caseautomation = "bad" @@ -155,35 +157,30 @@ def test_custom_workitem(self): req = Requirement() with self.assertRaises(PyleroLibException): req.reqtype = "bad" - req.reqtype = 'functional' + req.reqtype = "functional" def test_uri_obj(self): - testrun2 = TestRun(project_id=DEFAULT_PROJ, - test_run_id=TEST_RUN_ID) + testrun2 = TestRun(project_id=DEFAULT_PROJ, test_run_id=TEST_RUN_ID) self.assertEqual(testrun2.template, "example") - new_template = TestRun.create_template(DEFAULT_PROJ, - TEMPLATE_ID, - "example", - title=TEMPLATE_TITLE) + new_template = TestRun.create_template( + DEFAULT_PROJ, TEMPLATE_ID, "example", title=TEMPLATE_TITLE + ) testrun2.template = new_template - self.assertEqual(testrun2.template, - new_template.test_run_id) - self.assertNotEqual(testrun2.template, - "example") + self.assertEqual(testrun2.template, new_template.test_run_id) + self.assertNotEqual(testrun2.template, "example") def test_bad_character(self): - """this test validates that non UTF-8 characters will cause an error - """ + """this test validates that non UTF-8 characters will cause an error""" test_case = TestCase() steps = TestSteps() with self.assertRaises(PyleroLibException): # check _obj_setter - test_case.status = u"é".encode('latin') + test_case.status = "é".encode("latin") with self.assertRaises(PyleroLibException): # check _custom_setter - test_case.tcmscaseid = u"é".encode('latin') + test_case.tcmscaseid = "é".encode("latin") with self.assertRaises(PyleroLibException): # check _regular_setter - test_case.title = u"é".encode('latin') + test_case.title = "é".encode("latin") with self.assertRaises(PyleroLibException): # check _arr_obj_setter - steps.keys = [u"é".encode('latin')] + steps.keys = ["é".encode("latin")] if __name__ == "__main__": diff --git a/src/unit_tests/document_test.py b/src/unit_tests/document_test.py index 84864df..aa7cfe3 100644 --- a/src/unit_tests/document_test.py +++ b/src/unit_tests/document_test.py @@ -1,11 +1,11 @@ -''' +""" Created on Apr 13, 2015 @author: szacks -''' +""" import datetime - import unittest + from pylero.document import Document from pylero.test_run import TestRun from pylero.work_item import TestCase @@ -21,12 +21,16 @@ class DocumentTest(unittest.TestCase): - @classmethod def setUpClass(cls): cls.doc_create = Document.create( - Document.default_project, "Testing", DOC_NAME, - "Document_Test", ["testcase"], "testspecification") + Document.default_project, + "Testing", + DOC_NAME, + "Document_Test", + ["testcase"], + "testspecification", + ) def test_002_get_documents(self): lst_doc = Document.get_documents(Document.default_project, "Testing") @@ -34,14 +38,14 @@ def test_002_get_documents(self): self.assertIsInstance(doc, Document) def test_003_query(self): - lst_doc = Document.query("project.id:" + Document.default_project, - limit=10) + lst_doc = Document.query("project.id:" + Document.default_project, limit=10) doc = lst_doc[0] self.assertIsInstance(doc, Document) def test_004_get_name(self): - self.doc_get1 = Document(project_id=Document.default_project, - doc_with_space="Testing/" + DOC_NAME) + self.doc_get1 = Document( + project_id=Document.default_project, doc_with_space="Testing/" + DOC_NAME + ) self.assertIsInstance(self.doc_get1, Document) def test_005_get_uri(self): @@ -77,20 +81,25 @@ def test_008_doc_test_run_template(self): global TEST_RUN_ID doc_with_space = self.doc_create.space self.doc_create.session.tx_begin() - tmp = TestRun.create_template(project_id=Document.default_project, - template_id=TEMPLATE_ID, - doc_with_space=doc_with_space, - title=TEMPLATE_TITLE) + tmp = TestRun.create_template( + project_id=Document.default_project, + template_id=TEMPLATE_ID, + doc_with_space=doc_with_space, + title=TEMPLATE_TITLE, + ) TEMPLATE_ID = tmp.test_run_id - tr = TestRun.create(project_id=Document.default_project, - test_run_id=TEST_RUN_ID, - template=TEMPLATE_ID, - title=TEST_RUN_TITLE) + tr = TestRun.create( + project_id=Document.default_project, + test_run_id=TEST_RUN_ID, + template=TEMPLATE_ID, + title=TEST_RUN_TITLE, + ) TEST_RUN_ID = tr.test_run_id self.assertEqual(len(tr.records), 1) self.assertEqual(tr.records[0].test_case_id, WI_ID) self.doc_create.session.tx_commit() + if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName'] unittest.main() diff --git a/src/unit_tests/plan_test.py b/src/unit_tests/plan_test.py index cd36637..9510e66 100644 --- a/src/unit_tests/plan_test.py +++ b/src/unit_tests/plan_test.py @@ -1,7 +1,7 @@ import datetime import os - import unittest + from pylero.exceptions import PyleroLibException from pylero.plan import Plan from pylero.work_item import Requirement @@ -17,21 +17,24 @@ class PlanTest(unittest.TestCase): - @classmethod def setUpClass(cls): - req1 = Requirement.create(DEFAULT_PROJ, - "regression", - "regression", - severity="should_have", - reqtype="functional") + req1 = Requirement.create( + DEFAULT_PROJ, + "regression", + "regression", + severity="should_have", + reqtype="functional", + ) cls.NEW_REQ = req1.work_item_id - req2 = Requirement.create(DEFAULT_PROJ, - "regression", - "regression", - severity="should_have", - reqtype="functional") + req2 = Requirement.create( + DEFAULT_PROJ, + "regression", + "regression", + severity="should_have", + reqtype="functional", + ) cls.NEW_REQ2 = req2.work_item_id def test_001_create_template(self): @@ -41,7 +44,8 @@ def test_001_create_template(self): The parent attribute is not returned """ template = Plan.create_plan_template( - TEMPLATE_ID, "Regression", DEFAULT_PROJ, None) + TEMPLATE_ID, "Regression", DEFAULT_PROJ, None + ) self.assertIsNotNone(template.plan_id) self.assertTrue(template.is_template) @@ -50,8 +54,7 @@ def test_002_create_plan(self): * creates a test riun based on the template created in previous test * Verifies that the returned object exists and is not a template """ - plan = Plan.create( - PLAN_ID, "Regression", DEFAULT_PROJ, None, TEMPLATE_ID) + plan = Plan.create(PLAN_ID, "Regression", DEFAULT_PROJ, None, TEMPLATE_ID) self.assertIsNotNone(plan.plan_id) self.assertFalse(plan.is_template) @@ -102,6 +105,7 @@ def test_010_delete(self): with self.assertRaises(PyleroLibException): Plan(project_id=DEFAULT_PROJ, plan_id=PLAN_ID) + if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName'] unittest.main() diff --git a/src/unit_tests/revert_tests.py b/src/unit_tests/revert_tests.py index 65944dc..1d61c9a 100644 --- a/src/unit_tests/revert_tests.py +++ b/src/unit_tests/revert_tests.py @@ -21,14 +21,13 @@ def revert_svn(): svn.set_store_passwords(False) svn.checkout(svn_url, LOCAL_DIR) svn_log = svn.log(LOCAL_DIR) -# first_revision = svn_log[-1].revision + # first_revision = svn_log[-1].revision for log in svn_log: if log.revision.number == REVERT_TO: break first_revision = log.revision last_revision = svn_log[0].revision - svn.merge(LOCAL_DIR, last_revision, LOCAL_DIR, first_revision, - LOCAL_DIR) + svn.merge(LOCAL_DIR, last_revision, LOCAL_DIR, first_revision, LOCAL_DIR) svn.checkin(LOCAL_DIR, "revert to original version") # The original Example template query has an extra colon. # After revert, must fix that. diff --git a/src/unit_tests/test_run_test.py b/src/unit_tests/test_run_test.py index e5bc077..8c46f05 100644 --- a/src/unit_tests/test_run_test.py +++ b/src/unit_tests/test_run_test.py @@ -1,12 +1,12 @@ -''' +""" Created on Apr 19, 2015 @author: szacks -''' +""" import datetime import os - import unittest + from pylero.exceptions import PyleroLibException from pylero.plan import Plan from pylero.test_record import TestRecord @@ -34,34 +34,39 @@ class TestRunTest(unittest.TestCase): - @classmethod def setUpClass(cls): - tc1 = TestCase.create(DEFAULT_PROJ, - "regression", - "regression", - caseimportance="high", - caselevel="component", - caseautomation="notautomated", - caseposneg="positive", - testtype="functional", - subtype1="-") + tc1 = TestCase.create( + DEFAULT_PROJ, + "regression", + "regression", + caseimportance="high", + caselevel="component", + caseautomation="notautomated", + caseposneg="positive", + testtype="functional", + subtype1="-", + ) cls.NEW_TEST_CASE = tc1.work_item_id - tc2 = TestCase.create(DEFAULT_PROJ, - "regression", - "regression", - caseimportance="high", - caselevel="component", - caseautomation="notautomated", - caseposneg="positive", - testtype="functional", - subtype1="-") + tc2 = TestCase.create( + DEFAULT_PROJ, + "regression", + "regression", + caseimportance="high", + caselevel="component", + caseautomation="notautomated", + caseposneg="positive", + testtype="functional", + subtype1="-", + ) cls.NEW_TEST_CASE2 = tc2.work_item_id - Plan.create(plan_id=PLAN_ID, - plan_name="regression", - project_id=DEFAULT_PROJ, - parent_id=None, - template_id="release") + Plan.create( + plan_id=PLAN_ID, + plan_name="regression", + project_id=DEFAULT_PROJ, + parent_id=None, + template_id="release", + ) cls.NEW_PLAN = PLAN_ID def test_001_create_template(self): @@ -74,20 +79,28 @@ def test_001_create_template(self): """ global TEMPLATE_ID template = TestRun.create_template( - DEFAULT_PROJ, TEMPLATE_ID, "Empty", title=TEMPLATE_TITLE, - arch="i386") + DEFAULT_PROJ, TEMPLATE_ID, "Empty", title=TEMPLATE_TITLE, arch="i386" + ) TEMPLATE_ID = template.test_run_id self.assertIsNotNone(template.test_run_id) self.assertTrue(template.is_template) self.assertEqual(template.arch, "i386") with self.assertRaises(PyleroLibException): template = TestRun.create_template( - DEFAULT_PROJ, TEMPLATE_ID + "1", "Empty", TEMPLATE_TITLE + "1", - arch="BAD") + DEFAULT_PROJ, + TEMPLATE_ID + "1", + "Empty", + TEMPLATE_TITLE + "1", + arch="BAD", + ) with self.assertRaises(PyleroLibException): template = TestRun.create_template( - DEFAULT_PROJ, TEMPLATE_ID + "2", "Empty", TEMPLATE_TITLE + "2", - notaparm="BAD") + DEFAULT_PROJ, + TEMPLATE_ID + "2", + "Empty", + TEMPLATE_TITLE + "2", + notaparm="BAD", + ) def test_002_create_run(self): """This test does the following: @@ -95,8 +108,7 @@ def test_002_create_run(self): * Verifies that the returned object exists and is not a template """ global TEST_RUN_ID - tr = TestRun.create( - DEFAULT_PROJ, TEST_RUN_ID, TEMPLATE_ID, TEST_RUN_TITLE) + tr = TestRun.create(DEFAULT_PROJ, TEST_RUN_ID, TEMPLATE_ID, TEST_RUN_TITLE) TEST_RUN_ID = tr.test_run_id self.assertIsNotNone(tr.test_run_id) self.assertFalse(tr.is_template) @@ -154,37 +166,54 @@ def test_005_test_record_by_fields(self): tr = TestRun(project_id=DEFAULT_PROJ, test_run_id=TEST_RUN_ID) with self.assertRaises(PyleroLibException): tr.add_test_record_by_fields( - self.NEW_TEST_CASE, "invalid", "No Comment", - tr.logged_in_user_id, datetime.datetime.now(), "50.5") + self.NEW_TEST_CASE, + "invalid", + "No Comment", + tr.logged_in_user_id, + datetime.datetime.now(), + "50.5", + ) tr.add_test_record_by_fields( - self.NEW_TEST_CASE, "passed", "No Comment", tr.logged_in_user_id, - datetime.datetime.now(), "50.5") + self.NEW_TEST_CASE, + "passed", + "No Comment", + tr.logged_in_user_id, + datetime.datetime.now(), + "50.5", + ) tr.reload() self.assertEqual(tr.status, "finished") # test that the same case cannot be added multiple times. with self.assertRaises(PyleroLibException): tr.add_test_record_by_fields( - self.NEW_TEST_CASE, "passed", "No Comment", - tr.logged_in_user_id, datetime.datetime.now(), "50.5") + self.NEW_TEST_CASE, + "passed", + "No Comment", + tr.logged_in_user_id, + datetime.datetime.now(), + "50.5", + ) tr.reload() rec = tr.records[-1] - tr.add_attachment_to_test_record( - rec.test_case_id, ATTACH_PATH, ATTACH_TITLE) + tr.add_attachment_to_test_record(rec.test_case_id, ATTACH_PATH, ATTACH_TITLE) tr.reload() rec = tr.records[-1] self.assertTrue(len(rec.attachments) == 1) self.assertEqual(rec.attachments[0].title, ATTACH_TITLE) - tr.delete_attachment_from_test_record(rec.test_case_id, - rec.attachments[0].filename) + tr.delete_attachment_from_test_record( + rec.test_case_id, rec.attachments[0].filename + ) tr.reload() rec = tr.records[-1] self.assertEqual(rec.attachments, []) - tr.update_test_record_by_fields(rec.test_case_id, - rec.result, - "Yes Comment", - rec.executed_by, - rec.executed, - rec.duration) + tr.update_test_record_by_fields( + rec.test_case_id, + rec.result, + "Yes Comment", + rec.executed_by, + rec.executed, + rec.duration, + ) tr.reload() rec = tr.records[-1] self.assertEqual(rec.comment, "Yes Comment") @@ -272,23 +301,35 @@ def test_009_dynamic_records(self): * reloads * verifies that the record has been added """ - TestCase.create(DEFAULT_PROJ, - TIME_STAMP, "regression", - caseimportance="high", - caselevel="component", - caseautomation="notautomated", - caseposneg="positive", - testtype="functional", - subtype1="-") - tr = TestRun.create(DEFAULT_PROJ, "querytest-%s" % TIME_STAMP, - "Example", - "querytest-%s" % TIME_STAMP, query=TIME_STAMP) + TestCase.create( + DEFAULT_PROJ, + TIME_STAMP, + "regression", + caseimportance="high", + caselevel="component", + caseautomation="notautomated", + caseposneg="positive", + testtype="functional", + subtype1="-", + ) + tr = TestRun.create( + DEFAULT_PROJ, + "querytest-%s" % TIME_STAMP, + "Example", + "querytest-%s" % TIME_STAMP, + query=TIME_STAMP, + ) self.assertEqual(tr.select_test_cases_by, "dynamicQueryResult") num_recs = len(tr.records) test_case_id = tr.records[0].test_case_id - tr.update_test_record_by_fields(test_case_id, "blocked", "comment", - tr.logged_in_user_id, - datetime.datetime.now(), 0) + tr.update_test_record_by_fields( + test_case_id, + "blocked", + "comment", + tr.logged_in_user_id, + datetime.datetime.now(), + 0, + ) tr.reload() self.assertEqual(num_recs, len(tr.records)) self.assertEqual(test_case_id, tr.records[0].test_case_id) @@ -348,9 +389,7 @@ def test_013_incident_report_test(self): * Verifies that an Incident Report was Created """ tr = TestRun(project_id=DEFAULT_PROJ, test_run_id=TEST_RUN_ID) - tests = [["Test 1", "Result 1"], - ["Test 2", "Result 2"], - ["Test 3", "Result 3"]] + tests = [["Test 1", "Result 1"], ["Test 2", "Result 2"], ["Test 3", "Result 3"]] set_steps = [] for test in tests: ts = TestStep() @@ -380,8 +419,7 @@ def test_013_incident_report_test(self): linked_work_items = tc.linked_work_items_derived idx = len(linked_work_items) - 1 item_id = linked_work_items[idx].work_item_id - incident = IncidentReport(project_id=DEFAULT_PROJ, - work_item_id=item_id) + incident = IncidentReport(project_id=DEFAULT_PROJ, work_item_id=item_id) self.assertIsNotNone(incident) diff --git a/src/unit_tests/work_item_test.py b/src/unit_tests/work_item_test.py index c060ba5..968c3cf 100644 --- a/src/unit_tests/work_item_test.py +++ b/src/unit_tests/work_item_test.py @@ -1,11 +1,11 @@ -''' +""" Created on Apr 15, 2015 @author: szacks -''' +""" import os - import unittest + from pylero.exceptions import PyleroLibException from pylero.test_step import TestStep from pylero.work_item import Requirement @@ -18,165 +18,148 @@ class WorkItemTest(unittest.TestCase): - @classmethod def setUpClass(cls): - tc = TestCase.create(DEFAULT_PROJ, - "regression", - "regression", - caseimportance="high", - caselevel="component", - caseautomation="notautomated", - caseposneg="positive", - testtype="functional", - subtype1="-") - req = Requirement.create(DEFAULT_PROJ, - "regression _link", - "regression link", - reqtype="functional", - severity="should_have", - priority = "50.0") + tc = TestCase.create( + DEFAULT_PROJ, + "regression", + "regression", + caseimportance="high", + caselevel="component", + caseautomation="notautomated", + caseposneg="positive", + testtype="functional", + subtype1="-", + ) + req = Requirement.create( + DEFAULT_PROJ, + "regression _link", + "regression link", + reqtype="functional", + severity="should_have", + priority="50.0", + ) cls.work_item_id = tc.work_item_id cls.work_item_uri = tc.uri cls.work_item_id_2 = req.work_item_id cls.work_item_uri_2 = req.uri def test_001_query(self): - results = TestCase.query( - "project.id:%s AND title:regression" % (DEFAULT_PROJ)) + results = TestCase.query("project.id:%s AND title:regression" % (DEFAULT_PROJ)) tc = results[0] self.assertIsNone(tc.title) results2 = TestCase.query( "project.id:%s AND title:regression" % (DEFAULT_PROJ), - fields=["work_item_id", "title"]) + fields=["work_item_id", "title"], + ) tc = results2[0] self.assertIsNotNone(tc.title) results3 = TestCase.query( "project.id:%s AND title:regression" % (DEFAULT_PROJ), - fields=["work_item_id", "caseautomation"]) + fields=["work_item_id", "caseautomation"], + ) tc = results3[0] self.assertEqual(tc.caseautomation, "notautomated") def test_002_get_item(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertIsNotNone(tc.uri) def test_003_add_assignee(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) with self.assertRaises(PyleroLibException): tc.add_assignee("invalid user") self.assertTrue(tc.add_assignee(tc.logged_in_user_id)) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(tc2.assignee) self.assertEqual(tc2.assignee[0].user_id, tc2.logged_in_user_id) def test_004_add_approvee(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) with self.assertRaises(PyleroLibException): tc.add_approvee("invalid user") tc.add_approvee(tc.logged_in_user_id) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.approvals) == 1) approval = tc2.approvals[0] self.assertEqual(approval.status, "waiting") self.assertEqual(approval.user_id, tc.logged_in_user_id) def test_005_add_category(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) with self.assertRaises(PyleroLibException): tc.add_category("invalid category") self.assertTrue(tc.add_category("filesystems")) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.categories) == 1) cat = tc2.categories[0] self.assertEqual(cat.category_id, "filesystems") def test_006_add_hyperlink(self): # TODO: check if an invalid hyperlink can be passed in. - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) with self.assertRaises(PyleroLibException): tc.add_hyperlink(HYPERLINK, "invalid") self.assertTrue(tc.add_hyperlink(HYPERLINK, "ref_ext")) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.hyperlinks) == 1) link = tc2.hyperlinks[0] self.assertEqual(link.uri, HYPERLINK) self.assertEqual(link.role, "ref_ext") def test_007_add_linked_work_item(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(tc.add_linked_item(self.work_item_id_2, "verifies")) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.linked_work_items) == 1) link = tc2.linked_work_items[0] self.assertEqual(link.work_item_id, self.work_item_id_2) self.assertEqual(link.role, "verifies") - req3 = Requirement(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id_2) + req3 = Requirement(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id_2) self.assertTrue(len(req3.linked_work_items_derived) == 1) link = req3.linked_work_items_derived[0] self.assertEqual(link.work_item_id, self.work_item_id) self.assertEqual(link.role, "verifies") def test_008_create_attachment(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) tc.create_attachment(ATTACH_PATH, "Attached File") - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.attachments) == 1) attach = tc2.attachments[0] self.assertEqual(attach.author, tc2.logged_in_user_id) self.assertEqual(attach.title, "Attached File") def test_009_create_comment(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) tc.create_comment("This is a comment") - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.comments) == 1) comment = tc2.comments[0] self.assertEqual(comment.text, "This is a comment") def test_010_delete_attachment(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) attach = tc.attachments[0] tc.delete_attachment(attach.attachment_id) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertEqual(tc2.attachments, []) def test_011_edit_approval(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) with self.assertRaises(PyleroLibException): tc.edit_approval("invalid user", "approved") with self.assertRaises(PyleroLibException): tc.edit_approval(tc.logged_in_user_id, "invalid status") tc.edit_approval(tc.logged_in_user_id, "approved") - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(len(tc2.approvals) == 1) approval = tc2.approvals[0] self.assertEqual(approval.status, "approved") self.assertEqual(approval.user_id, tc.logged_in_user_id) def test_012_get_back_linked_work_items(self): - req = Requirement(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id_2) + req = Requirement(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id_2) items = req.get_back_linked_work_items() self.assertTrue(len(items) == 1) wi = items[0] @@ -204,63 +187,49 @@ def test_014_steps(self): ts3 = TestStep() ts3.values = test3 set_steps = [ts1, ts2, ts3] - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) tc.set_test_steps(set_steps) - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) get_steps = tc2.get_test_steps() - self.assertEqual(get_steps.steps[0].values[0].content, - ts1.values[0].content) - self.assertEqual(get_steps.steps[0].values[1].content, - ts1.values[1].content) - self.assertEqual(get_steps.steps[1].values[0].content, - ts2.values[0].content) - self.assertEqual(get_steps.steps[1].values[1].content, - ts2.values[1].content) - self.assertEqual(get_steps.steps[2].values[0].content, - ts3.values[0].content) - self.assertEqual(get_steps.steps[2].values[1].content, - ts3.values[1].content) + self.assertEqual(get_steps.steps[0].values[0].content, ts1.values[0].content) + self.assertEqual(get_steps.steps[0].values[1].content, ts1.values[1].content) + self.assertEqual(get_steps.steps[1].values[0].content, ts2.values[0].content) + self.assertEqual(get_steps.steps[1].values[1].content, ts2.values[1].content) + self.assertEqual(get_steps.steps[2].values[0].content, ts3.values[0].content) + self.assertEqual(get_steps.steps[2].values[1].content, ts3.values[1].content) def test_015_remove_assignee(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertFalse(tc.remove_assignee("invalid user")) self.assertFalse(tc.remove_assignee("oramraz")) self.assertTrue(tc.remove_assignee(tc.logged_in_user_id)) def test_016_remove_category(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertFalse(tc.remove_category("invalid cat")) self.assertFalse(tc.remove_category("clustering")) self.assertTrue(tc.remove_category("filesystems")) def test_017_remove_hyperlink(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertTrue(tc.remove_hyperlink(HYPERLINK)) def test_018_remove_linked_item(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) - self.assertTrue(tc.remove_linked_item(self.work_item_id_2, - "verifies")) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) + self.assertTrue(tc.remove_linked_item(self.work_item_id_2, "verifies")) def test_019_update(self): - tc = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) tc.status = "approved" tc.update() - tc2 = TestCase(project_id=DEFAULT_PROJ, - work_item_id=self.work_item_id) + tc2 = TestCase(project_id=DEFAULT_PROJ, work_item_id=self.work_item_id) self.assertEqual(tc2.status, "approved") def test_020_query_with_URI_field(self): results = TestCase.query( "project.id:%s AND title:regression" % (DEFAULT_PROJ), - fields=["work_item_id", "author"]) + fields=["work_item_id", "author"], + ) tc = results[0] self.assertIsNotNone(tc.author) diff --git a/tier_tests.py b/tier_tests.py index 7d88cee..9d044b1 100644 --- a/tier_tests.py +++ b/tier_tests.py @@ -2,6 +2,7 @@ import subprocess import sys + # this script execute tier testsing for pylero # if the first argument is "tier0" it tests tier0 # if the first argument is "tier1" it tests tier1 @@ -10,17 +11,16 @@ def get_command(x): return { - 'tier0': 'attribute_test', - 'tier1': 'test_run_test document_test work_item_test plan_test', - 'all': 'attribute_test test_run_test document_test' - ' work_item_test plan_test' + "tier0": "attribute_test", + "tier1": "test_run_test document_test work_item_test plan_test", + "all": "attribute_test test_run_test document_test" " work_item_test plan_test", }.get(x) if __name__ == "__main__": - nose = 'nose2 --plugin nose2.plugins.junitxml --junit-xml' - coverage = ' --with-coverage --coverage-report xml' - src = ' -s src/unit_tests ' + nose = "nose2 --plugin nose2.plugins.junitxml --junit-xml" + coverage = " --with-coverage --coverage-report xml" + src = " -s src/unit_tests " tests = None if len(sys.argv) == 2: