Skip to content

Commit 06fe765

Browse files
Merge pull request #28 from klehman-rally/vsm-17
Vsm 17
2 parents afa7759 + f6aa316 commit 06fe765

58 files changed

Lines changed: 2381 additions & 369 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

LICENSE

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright © Broadcom, Inc. - 2018-2024; CA Technologies - 2015-2018; Rally Software Development Corp. - 2010-2015
1+
Copyright © Broadcom, Inc. - 2018-2025; CA Technologies - 2015-2018; Rally Software Development Corp. - 2010-2015
22
All rights reserved.
33

44
License for pyral (a Python toolkit for the Rally REST API)
@@ -31,5 +31,4 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3131
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3232
SUCH DAMAGE.
3333

34-
Rally Software Development® is a registered trademark of Rally Software Development Corp.
3534

PKG-INFO

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
Metadata-Version: 1.1
22
Name: pyral
3-
Version: 1.6.0
3+
Version: 1.7.0
44
Summary: Python toolkit for Rally REST API
55
Home-page: https://github.com/RallyTools/RallyRestToolkitForPython
66
Author: Kip Lehman (Broadcom, Agile Operations Division)
77
License: BSD
8-
Download-URL: https://github.com/RallyTools/RallyRestToolkitForPython/raw/master/dists/pyral-1.6.0.zip
8+
Download-URL: https://github.com/RallyTools/RallyRestToolkitForPython/raw/master/dists/pyral-1.7.0.zip
99
Description: This is the README file for pyral, a package implementing a
1010
Pythonic interface to the Rally REST API
1111

@@ -25,9 +25,9 @@ Description: This is the README file for pyral, a package implementing a
2525
Requirements
2626
------------
2727

28-
The pyral package requires the use of Kenneth Reitz's requests package using version 2.28.0 or better.
28+
The pyral package requires the use of Kenneth Reitz's requests package using version 2.31.x or better.
2929
The requests package can be found via the Python Package Index site (http://pypi/python.org/index).
30-
The most recent release of pyral (1.6.0) has been tested with requests 2.31.0.
30+
The most recent release of pyral (1.7.0) has been tested with requests 2.32.5.
3131

3232

3333
Installation
@@ -39,6 +39,8 @@ Description: This is the README file for pyral, a package implementing a
3939

4040
pip install pyral
4141

42+
This approach can probably also use pipex or poetry (although I have not confirmed that).
43+
4244
Alternatively if you've got the tar.gz or zip distribution on hand, as long as you've
4345
satisfied the dependency requirement of the requests packages, you can use the setup mechanism.
4446
Once the requests package has been installed, run the setup.py program supplied with
@@ -64,22 +66,20 @@ Description: This is the README file for pyral, a package implementing a
6466
Obtain the zip file containing the HTML and CSS files comprising the document set for pyral.
6567
Unzip in a suitable location and point your web browser to the doc/build/html/index.html file.
6668

67-
The rendered documentation is also available at http://pyral.readthedocs.io/en/latest/
68-
and http://pythonhosted.org/pyral
69+
The rendered documentation is also available at http://pyral.readthedocs.io/en/latest/ .
6970

7071

7172
Keywords: rally,api
72-
Requires: requests>=2.28.1
73+
Requires: requests>=2.31.2
7374
Platform: any
7475
Classifier: Development Status :: 5 - Production/Stable
7576
Classifier: Environment :: Web Environment
7677
Classifier: Intended Audience :: Developers
7778
Classifier: License :: OSI Approved :: BSD License
7879
Classifier: Operating System :: OS Independent
7980
Classifier: Programming Language :: Python
80-
Classifier: Programming Language :: Python :: 3.9
81-
Classifier: Programming Language :: Python :: 3.10
82-
Classifier: Programming Language :: Python :: 3.11
8381
Classifier: Programming Language :: Python :: 3.12
82+
Classifier: Programming Language :: Python :: 3.13
83+
Classifier: Programming Language :: Python :: 3.14
8484
Classifier: Topic :: Internet :: WWW/HTTP
8585
Classifier: Topic :: Software Development :: Libraries

README.rst

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ pip, the Python package installation utility.::
3838
Alternatively, if you've got the tar.gz or zip distribution on hand, as long as you've
3939
satisfied the dependency requirement on the requests package, you can use the setup mechanism.
4040
Obtain the requests_ package and install it according to that package's directions.
41-
Use of requests-2.28.x or better is recommended for use with pyral.
41+
Use of requests-2.32.x or better is recommended for use with pyral.
4242
The requests_ package can be found via the Python Package Index site (http://pypi/python.org/index).
43-
The most recent release of pyral (1.6.0) has been tested using requests 2.31.0.
43+
The most recent release of pyral (1.7.0) has been tested using requests 2.32.5.
4444

4545
Unpack the ``pyral`` distribution file (zip or tar.gz) and then install the pyral_ package.
4646

@@ -61,11 +61,11 @@ relevant packages.
6161
::
6262

6363
$ python
64-
Python 3.11.5 [other Python interpreter info elided ...]
64+
Python 3.13.7 [other Python interpreter info elided ...]
6565
>> import requests
6666
>> import pyral
6767
>> pyral.__version__
68-
(1, 6, 0)
68+
(1, 7, 0)
6969

7070

7171
30 second highlight
@@ -241,13 +241,22 @@ The item names in config files **are** case sensitive.
241241
Prerequisites
242242
-------------
243243

244-
* Python 3.9, 3,10, 3.11 or 3.12 (this package not tested with earlier versions of Python 3.x)
245-
* The requests_ package, 2.28.1 or better, requests 2.31.0 or beyond is recommended.
244+
* Python any of (3.12, 3.13 and 3.14) (this package not tested with earlier versions of Python 3.x)
245+
* The requests_ package, 2.31.x or better, requests 2.32.5 or beyond is recommended.
246246

247247
.. _requests: http://github.com/kennethreitz/requests
248248

249249
Versions
250250
--------
251+
**1.7.0**
252+
Explicitly state support for Python 3.12, 3.13 and 3.14
253+
Fixed bug with pryal.restapi.Rally.addCollectionItems method, a collection_name must be provided.
254+
Added support for VSM* related entities (VSMProduct, VSMComponent, VSMIncident, VSMChange, VSMDeploy,
255+
VSMInvestmentCategorytoInvestmentIntentMap, VSMProductAnalyticsMetric, VSMTarget, VSMMeasure).
256+
Added support for creating and updating multiple items of the same entity type in one call via
257+
the restapi.createMultiple and restapi.updateMultiple methods.
258+
Drop any mention of support for versions 3.11 and earlier.
259+
251260
**1.6.0**
252261
Eliminated use of six package.
253262
Added support for Risk, Objective, KeyResult and CapacityPlan* entities.
@@ -359,7 +368,7 @@ TODO
359368
License
360369
-------
361370

362-
BSD3-style license. Copyright (c) 2018-2024 Broadcom, Inc., 2015-2018 CA Technologies, 2010-2015 Rally Software Development.
371+
BSD3-style license. Copyright (c) 2018-2025 Broadcom, Inc., 2015-2018 CA Technologies, 2010-2015 Rally Software Development.
363372

364373
See the LICENSE file provided with the source distribution for full details.
365374

README.short

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ that may be references or collections via the familiar dot '.' notation.
1717
Requirements
1818
------------
1919

20-
The pyral package requires the use of Kenneth Reitz's requests package using version 2.28.0 or better.
20+
The pyral package requires the use of Kenneth Reitz's requests package using version 2.31.x or better.
2121
The requests package can be found via the Python Package Index site (http://pypi/python.org/index).
22-
The most recent release of pyral (1.6.0) has been tested with requests 2.31.0.
22+
The most recent release of pyral (1.7.0) has been tested with requests 2.32.5.
2323

2424

2525
Installation
@@ -31,6 +31,8 @@ pip, the Python package installation utility.::
3131

3232
pip install pyral
3333

34+
This approach can probably also use pipex or poetry (although I have not confirmed that).
35+
3436
Alternatively if you've got the tar.gz or zip distribution on hand, as long as you've
3537
satisfied the dependency requirement of the requests packages, you can use the setup mechanism.
3638
Once the requests package has been installed, run the setup.py program supplied with
@@ -56,6 +58,5 @@ Documentation
5658
Obtain the zip file containing the HTML and CSS files comprising the document set for pyral.
5759
Unzip in a suitable location and point your web browser to the doc/build/html/index.html file.
5860

59-
The rendered documentation is also available at http://pyral.readthedocs.io/en/latest/
60-
and http://pythonhosted.org/pyral
61+
The rendered documentation is also available at http://pyral.readthedocs.io/en/latest/ .
6162

VERSIONS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,8 @@
162162
Updated supported Python versions to 3.9, 3.10, 3.11 and 3.12. No longer requires six package.
163163
Fixed defect in the getAllUsers method that prevented Users beyond the first page from being retrieved.
164164

165+
1.7.0 - Nov 2025
166+
Updated supported Python versions to 3.12, 3.13 and 3.14.
167+
Updated pytest to 8.3.x.
168+
Added support for VSM related Rally entities.
169+
Added support for creation/update of the multiple items via restapi.createMultiple and restapi.updateMultiple methods.

build_dist.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
import re
1515

1616
PACKAGE_NAME = "pyral"
17-
VERSION = "1.6.0"
17+
VERSION = "1.7.0"
1818

19-
AUX_FILES = ['MANIFEST.in',
19+
AUX_FILES = ['MANIFEST',
2020
'PKG-INFO',
2121
'LICENSE',
2222
'README.short',
@@ -27,6 +27,7 @@
2727
]
2828
EXAMPLES = ['periscope.py',
2929
'getitem.py',
30+
'getitemdesc.py',
3031
'showdefects.py',
3132
'crtask.py',
3233
'uptask.py',
@@ -58,7 +59,6 @@
5859
'doc/build/html/index.html',
5960
'doc/build/html/overview.html',
6061
'doc/build/html/interface.html',
61-
'doc/build/html/search.html',
6262
'doc/build/html/searchindex.js',
6363
'doc/build/html/objects.inv',
6464
'doc/build/html/_sources',
@@ -90,7 +90,6 @@
9090
'test/test_query.py',
9191
'test/test_ranking.py'
9292
'test/test_recyclebin.py'
93-
'test/test_search.py',
9493
'test/test_wksprj_setting.py',
9594
'test/test_workspaces.py'
9695
]
@@ -155,7 +154,7 @@ def package_meta(filename):
155154
raise Exception('No such file: %s' % filename)
156155
with open(filename, 'r') as pcf:
157156
content = pcf.read()
158-
chunk, setup = re.split('setup\(', content, maxsplit=1, flags=re.M)
157+
chunk, setup = re.split(r'setup\(', content, maxsplit=1, flags=re.M)
159158
consties = [line for line in chunk.split("\n")
160159
if (len(line) > 0 and line[0] == " ") or re.search(r'^[A-Z]', line)]
161160
assignments = "\n".join(consties)
-2.68 MB
Binary file not shown.

doc/source/conf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,16 @@
4141

4242
# General information about the project.
4343
project = 'pyral'
44-
copyright = 'Broadcom 2018-2024, CA Technologies 2015-2017, Rally Software Development 2010-2015'
44+
copyright = 'Broadcom 2018-2025, CA Technologies 2015-2017, Rally Software Development 2010-2015'
4545

4646
# The version info for the project you're documenting, acts as replacement for
4747
# |version| and |release|, also used in various other places throughout the
4848
# built documents.
4949
#
5050
# The short X.Y version.
51-
version = '1.6.0'
51+
version = '1.7.0'
5252
# The full version, including alpha/beta/rc tags.
53-
release = '1.6.0'
53+
release = '1.7.0'
5454

5555
# The language for content autogenerated by Sphinx. Refer to documentation
5656
# for a list of supported languages.

doc/source/interface.rst

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -455,21 +455,6 @@ Core REST methods and CRUD aliases
455455

456456
Returns a boolean indication of the disposition of the attempt to delete the item.
457457

458-
.. method:: search(keywords, \*\*kwargs)
459-
460-
Given a list of keywords or a string with space separated words, issue
461-
the relevant Rally WSAPI search request to find artifacts within the search
462-
scope that have any of the keywords in any of the artifact's text fields.
463-
464-
NOTE: The search functionality must be turned on for your subscription to use this method.
465-
466-
keyword arguments:
467-
- projectScopeUp = true/false (defaults to false)
468-
- projectScopeDown = true/false (defaults to false)
469-
- pagesize = n (defaults to 500)
470-
- start = n (defaults to 1)
471-
- limit = n (defaults to no limit)
472-
473458
pyral.Rally instance convenience methods
474459
----------------------------------------
475460

@@ -681,29 +666,57 @@ pyral.Rally instance convenience methods
681666
pyral.Rally experimental convenience methods
682667
--------------------------------------------
683668

684-
.. method:: addCollectionItems(target_item, collection_items)
669+
.. method:: createMultiple(entity_name, items, fields=None, workspace='current', project='current', **kwargs)
670+
671+
Given an entityName (for a valid Rally entity type) and a sequence of items (described below) and
672+
potential a list of Rally entity attribute names, use the Rally WSAPI /batch endpoint
673+
to effect the creation of items corresponding to the elements in list.
674+
The elements in the list MUST have information about ALL of the required fields of the Rally entity.
675+
The elements CAN have information about non-required fields.
676+
An item in the list of items CANNOT have any attributes that are of the Rally COLLECTION type.
677+
678+
items must be all dict instances OR items must be all pyral entity instances (or instances of "data" class).
679+
680+
.. method:: updateMultiple(entityName, items, fields=None, workspace='current', project='current', **kwargs)
681+
682+
Given an entityName (for a valid Rally entity type) and a sequence of items (described below)
683+
and a list of Rally entity attribute names that are to be updated (fields),
684+
use the Rally WSAPI /batch endpoint to effect the update of items corresponding
685+
to the elements in list of items.
686+
Each item MUST contain an identifying attribute name and value (usually ObjectID is used).
687+
The other elements in the list CAN only be attributes that are editable AND
688+
an item in the list of elements CANNOT have any attributes that are of the Rally COLLECTION type.
689+
If the items have attributes present with non-null values and the attribute name is NOT
690+
in the fields list, then those attributes will not be updated via this mechanism.
685691

686-
Given a target_item and a homogenous list of items whose type appears as a One to Many relationship
687-
in the target item, add the collection_items to the corresponding attribute in the target_item.
692+
items can be all dict instances OR items can be all pyral entity instances (or instances of "data" class).
693+
694+
.. method:: addCollectionItems(target_item, collection_name, collection_items)
695+
696+
Given a target_item, the name of the Collections attribute and a homogenous list of items whose type
697+
appears as a One to Many relationship in the target item, add the collection_items to the corresponding
698+
attribute in the target_item.
699+
700+
Returns the updated target_item.
688701

689702
::
690703

691704
...
692705
milestones = [milestone_1, milestone_2, milestone_3]
693706
story = rally.get('story', 'US123')
694-
rally.addCollectionItems(story, milestones)
707+
rally.addCollectionItems(story, 'Milestones', milestones)
695708

696709
.. warning::
697710

698711
This method only works when the collection attribute on the target_item is Modifiable.
699712
Consult the Rally WSAPI documentation for the target_item attributes to see whether
700713
the attribute of interest has a notation of 'Collection Modifiable yes'. If there is no
701-
'Colletion Modifiable' notation or the value for that is 'no', then use of this method
714+
'Collection Modifiable' notation or the value for that is 'no', then use of this method
702715
should not be attempted.
703716
At this time, the Rally WSAPI schema endpoint does not include information about
704717
'Collection Modifiable' for any of the attributes, you'll have to consult the documentation.
705718

706-
.. method:: dropCollectionItems(target_item, collection_items)
719+
.. method:: dropCollectionItems(target_item, collection_name, collection_items)
707720

708721
Given a target_item and a homogenous list of items whose type appears as a One to Many relationship
709722
in the target item, delete the collection_items to the corresponding attribute in the target_item

examples/cr_milestone.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env python
2+
3+
#################################################################################################
4+
#
5+
# cr_milestone.py -- Create a Milestone instance with a Name and TargetDate
6+
#
7+
USAGE = """
8+
Usage: cr_milestone.py <name> <target_date>
9+
"""
10+
#################################################################################################
11+
12+
import sys, os
13+
from pyral import Rally, rallyWorkset
14+
15+
#################################################################################################
16+
17+
errout = sys.stderr.write
18+
19+
#################################################################################################
20+
21+
def main(args):
22+
options = [opt for opt in args if opt.startswith('--')]
23+
args = [arg for arg in args if arg not in options]
24+
25+
if len(args) != 2:
26+
print("No arguments for the Milestone Name or TargetDate were specified")
27+
sys.exit(1)
28+
29+
server, user, password, apikey, workspace, project = rallyWorkset(options)
30+
if apikey:
31+
rally = Rally(server, apikey=apikey, workspace=workspace, project=project)
32+
else:
33+
rally = Rally(server, user=user, password=password, workspace=workspace, project=project)
34+
35+
target_project = rally.getProject()
36+
target_entity_name = 'Milestone'
37+
milestone_name, milestone_target_date = args[:2]
38+
info = { 'Name' : milestone_name,
39+
'TargetDate' : milestone_target_date
40+
}
41+
42+
43+
print(f"Creating {target_entity_name} ...")
44+
milestone = rally.put(target_entity_name, info)
45+
print(f"Created Milestone: {milestone.FormattedID} OID: {milestone.oid} Name: {milestone.Name} TargetDate: {milestone.TargetDate}")
46+
47+
#################################################################################################
48+
#################################################################################################
49+
50+
if __name__ == '__main__':
51+
main(sys.argv[1:])

0 commit comments

Comments
 (0)