Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
PyOTRS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Coopdevs
Som Connexió
OTRS
PyOTRS
Commits
54a9c77b
Commit
54a9c77b
authored
8 years ago
by
Robert Habermann
Browse files
Options
Downloads
Patches
Plain Diff
complete unittests
parent
793cbd58
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
pyotrs/lib.py
+59
-63
59 additions, 63 deletions
pyotrs/lib.py
tests/test_client.py
+374
-36
374 additions, 36 deletions
tests/test_client.py
tests/test_dynamic_field.py
+44
-3
44 additions, 3 deletions
tests/test_dynamic_field.py
with
477 additions
and
102 deletions
pyotrs/lib.py
+
59
−
63
View file @
54a9c77b
...
...
@@ -310,19 +310,36 @@ class DynamicField(object):
"""
PyOTRS DynamicField class
Args:
name (str): Name of OTRS DynamicField
name (str): Name of OTRS DynamicField
(required)
value (str): Value of OTRS DynamicField
search_operator (str): Search operator (defaults to:
"
Equals
"
)
Valid options are:
"
Equals
"
,
"
Like
"
,
"
GreaterThan
"
,
"
GreaterThanEquals
"
,
"
SmallerThan
"
,
"
SmallerThanEquals
"
search_patterns (list): List of patterns (str or datetime) to search for
.. warning::
**PyOTRS only supports OTRS 5 style!**
DynamicField representation changed between OTRS 4 and OTRS 5.
"""
def
__init__
(
self
,
name
,
value
):
SEARCH_OPERATORS
=
(
"
Equals
"
,
"
Like
"
,
"
GreaterThan
"
,
"
GreaterThanEquals
"
,
"
SmallerThan
"
,
"
SmallerThanEquals
"
,)
def
__init__
(
self
,
name
,
value
=
None
,
search_patterns
=
None
,
search_operator
=
"
Equals
"
):
self
.
name
=
name
self
.
value
=
value
if
not
isinstance
(
search_patterns
,
list
):
self
.
search_patterns
=
[
search_patterns
]
else
:
self
.
search_patterns
=
search_patterns
if
search_operator
not
in
DynamicField
.
SEARCH_OPERATORS
:
raise
NotImplementedError
(
"
Invalid Operator:
\"
{0}
\"
"
.
format
(
search_operator
))
self
.
search_operator
=
search_operator
def
__repr__
(
self
):
return
"
<{0}: {1}: {2}>
"
.
format
(
self
.
__class__
.
__name__
,
self
.
name
,
self
.
value
)
...
...
@@ -348,6 +365,21 @@ class DynamicField(object):
"""
return
{
"
Name
"
:
self
.
name
,
"
Value
"
:
self
.
value
}
def
to_dct_search
(
self
):
"""
represent DynamicField as dict for search operations
Returns:
**dict**: DynamicField as dict for search operations
"""
_lst
=
[]
for
item
in
self
.
search_patterns
:
if
isinstance
(
item
,
datetime
.
datetime
):
item
=
item
.
strftime
(
"
%Y-%m-%d %H:%M:%S
"
)
_lst
.
append
(
item
)
return
{
"
DynamicField_{0}
"
.
format
(
self
.
name
):
{
self
.
search_operator
:
_lst
}}
@classmethod
def
_dummy1
(
cls
):
"""
dummy1 data (for testing)
...
...
@@ -895,7 +927,7 @@ class Client(object):
attachment_list
=
None
,
dynamic_field_list
=
None
,
**
kwargs
):
"""
ticket_update_by_ticket_id_set_scout_id
"""
Create a Ticket
Args:
ticket (Ticket): a ticket object
...
...
@@ -1076,14 +1108,17 @@ class Client(object):
* ticket_search
* ticket_search_full_text
"""
def
ticket_search
(
self
,
**
kwargs
):
"""
Wrapper for search
ticket
def
ticket_search
(
self
,
dynamic_fields
=
None
,
**
kwargs
):
"""
Search for
ticket
Args:
**kwargs: Arbitrary keyword arguments (Dynamic Field).
dynamic_fields (list): List of DynamicField objects for which the search
should be performed
**kwargs: Arbitrary keyword arguments (not for DynamicField objects).
Returns:
**list** or **False**: The search result (as list) if successful, otherwise **False**.
**list** or **False**: The search result (as list) if successful, otherwise
**False**.
.. note::
If value of kwargs is a datetime object then this object will be
...
...
@@ -1098,6 +1133,10 @@ class Client(object):
"
SessionID
"
:
self
.
session_id_store
.
value
,
}
if
dynamic_fields
:
for
df
in
dynamic_fields
:
payload
.
update
(
df
.
to_dct_search
())
if
kwargs
is
not
None
:
for
key
,
value
in
kwargs
.
items
():
if
isinstance
(
value
,
datetime
.
datetime
):
...
...
@@ -1109,43 +1148,6 @@ class Client(object):
else
:
return
self
.
result
def
ticket_search_dynamic_field
(
self
,
name
,
value_list
,
operator
=
None
):
"""
Wrapper for search ticket
Args:
name (str): Name of DynamicField which the search should check
value_list (list): list of values to search for
operator (str): Search operator (defaults to:
"
Equals
"
)
Valid options are:
"
Equals
"
,
"
Like
"
,
"
GreaterThan
"
,
"
GreaterThanEquals
"
,
"
SmallerThan
"
,
"
SmallerThanEquals
"
Returns:
**list** or **False**: The search result (as list) if successful, otherwise **False**.
"""
if
not
self
.
session_id_store
.
value
:
raise
SessionNotCreated
(
"
Call session_create() or
"
"
session_restore_or_set_up_new() first
"
)
self
.
operation
=
"
TicketSearch
"
payload
=
{
"
SessionID
"
:
self
.
session_id_store
.
value
,
}
if
not
operator
:
operator
=
"
Equals
"
else
:
if
operator
not
in
[
"
Equals
"
,
"
Like
"
,
"
GreaterThan
"
,
"
GreaterThanEquals
"
,
"
SmallerThan
"
,
"
SmallerThanEquals
"
]:
raise
NotImplementedError
(
"
Invalid Operator:
\"
{0}
\"
"
.
format
(
operator
))
payload
.
update
({
"
DynamicField_{0}
"
.
format
(
name
):
{
operator
:
value_list
}})
if
not
self
.
_parse_and_validate_response
(
self
.
_send_request
(
payload
)):
return
False
else
:
return
self
.
result
def
ticket_search_full_text
(
self
,
pattern
):
"""
Wrapper for search ticket for full text search
...
...
@@ -1175,7 +1177,7 @@ class Client(object):
attachment_list
=
None
,
dynamic_field_list
=
None
,
**
kwargs
):
"""
ticket_update_by_ticket_id_set_scout_id
"""
Update a Ticket
Args:
...
...
@@ -1529,19 +1531,11 @@ class Client(object):
if
not
ticket_id
:
raise
ValueError
(
"
TicketID is None but Route requires
"
"
TicketID: {0}
"
.
format
(
route
))
if
route
.
startswith
((
"
/Link
"
,
"
/Possible
"
)):
self
.
_url
=
(
"
{0}/otrs/nph-genericinterface.pl/Webservice/
"
"
{1}{2}{3}
"
.
format
(
self
.
baseurl
,
self
.
webservicename_link
,
route
,
ticket_id
))
else
:
self
.
_url
=
(
"
{0}/otrs/nph-genericinterface.pl/Webservice/
"
"
{1}{2}{3}
"
.
format
(
self
.
baseurl
,
self
.
webservicename
,
route
,
ticket_id
))
self
.
_url
=
(
"
{0}/otrs/nph-genericinterface.pl/Webservice/
"
"
{1}{2}{3}
"
.
format
(
self
.
baseurl
,
self
.
webservicename
,
route
,
ticket_id
))
else
:
if
route
.
startswith
((
"
/Link
"
,
"
/Possible
"
)):
self
.
_url
=
(
"
{0}/otrs/nph-genericinterface.pl/Webservice/
"
...
...
@@ -1661,10 +1655,12 @@ class Client(object):
# LinkList result can be empty
if
self
.
operation
in
"
LinkList
"
:
_link_list
=
self
.
result_json
.
get
(
"
LinkList
"
,
None
)
if
_link_list
==
u
''
:
return
None
if
len
(
_link_list
):
return
_link_list
if
not
_link_list
:
self
.
result
=
None
return
True
else
:
self
.
result
=
_link_list
return
True
# now handle other operations
if
self
.
result_json
.
get
(
self
.
_result_type
,
None
):
...
...
This diff is collapsed.
Click to expand it.
tests/test_client.py
+
374
−
36
View file @
54a9c77b
This diff is collapsed.
Click to expand it.
tests/test_dynamic_field.py
+
44
−
3
View file @
54a9c77b
...
...
@@ -8,6 +8,7 @@ Test for PyOTRS DynamicField class
# make sure (early) that parent dir (main app) is in path
import
os.path
import
sys
from
datetime
import
datetime
import
unittest2
as
unittest
# from mock import MagicMock, patch
...
...
@@ -21,11 +22,51 @@ class DynamicFieldTests(unittest.TestCase):
def
test_init_blank
(
self
):
self
.
assertRaises
(
TypeError
,
DynamicField
)
def
test_init_name
_only
(
self
):
self
.
assertRaises
(
TypeError
,
DynamicField
,
name
=
"
foo
"
)
def
test_init_n
o_n
ame
(
self
):
self
.
assertRaises
(
TypeError
,
DynamicField
)
def
test_init_value_only
(
self
):
self
.
assertRaises
(
TypeError
,
DynamicField
,
value
=
"
bar
"
)
self
.
assertRaises
(
TypeError
,
DynamicField
,
value
=
"
foo
"
)
def
test_init_operator_default
(
self
):
dyn1
=
DynamicField
(
name
=
"
firstname
"
)
self
.
assertIsInstance
(
dyn1
,
DynamicField
)
self
.
assertEqual
(
dyn1
.
search_operator
,
"
Equals
"
)
def
test_init_operator_custom
(
self
):
dyn1
=
DynamicField
(
name
=
"
somedate
"
,
search_operator
=
"
SmallerThanEquals
"
)
self
.
assertIsInstance
(
dyn1
,
DynamicField
)
self
.
assertEqual
(
dyn1
.
search_operator
,
"
SmallerThanEquals
"
)
def
test_init_operator_invalid
(
self
):
self
.
assertRaises
(
NotImplementedError
,
DynamicField
,
name
=
"
somedate
"
,
search_operator
=
"
Foobar
"
)
def
test_init_non_list_pattern
(
self
):
dyn1
=
DynamicField
(
name
=
"
SomeName
"
,
search_patterns
=
"
foobar
"
,
search_operator
=
"
Equals
"
)
self
.
assertIsInstance
(
dyn1
.
search_patterns
,
list
)
def
test_init_list_pattern
(
self
):
dyn1
=
DynamicField
(
name
=
"
SomeName
"
,
search_patterns
=
[
"
foo
"
,
"
bar
"
],
search_operator
=
"
Equals
"
)
self
.
assertIsInstance
(
dyn1
.
search_patterns
,
list
)
def
test_dct_search
(
self
):
dyn1
=
DynamicField
(
name
=
"
SomeName
"
,
search_patterns
=
[
"
foo
"
,
"
bar
"
],
search_operator
=
"
Equals
"
)
self
.
assertEqual
(
dyn1
.
to_dct_search
(),
{
"
DynamicField_SomeName
"
:
{
"
Equals
"
:
[
"
foo
"
,
"
bar
"
]}})
def
test_dct_search_date
(
self
):
dyn1
=
DynamicField
(
name
=
"
SomeDate
"
,
search_patterns
=
[
datetime
(
2011
,
1
,
1
)],
search_operator
=
"
GreaterThan
"
)
self
.
assertEqual
(
dyn1
.
to_dct_search
(),
{
"
DynamicField_SomeDate
"
:
{
"
GreaterThan
"
:
[
"
2011-01-01 00:00:00
"
]}})
def
test_dummy1_static
(
self
):
dyn1
=
DynamicField
(
name
=
"
firstname
"
,
value
=
"
Jane
"
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment