Skip to content

Commit 7080987

Browse files
committed
Merge branch 'develop'
2 parents a4e4348 + 34a23ca commit 7080987

Some content is hidden

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

50 files changed

+1563
-44
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ __pycache__
55
.venv
66
venv
77
.idea
8+
9+
.DS_Store

CONTRIBUTING.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ To run an individual test method:
3535

3636
Note that due to the pytest config in the `pyproject.toml` file, all
3737
[Python logging](https://docs.python.org/3/howto/logging.html) should appear immediately
38-
as tests are executed.
38+
as tests are executed. If you are using VSCode, you can see the logging by selecting
39+
"Python Test Log" in the "Output" panel.
3940

4041
## Testing the client in a Python shell
4142

@@ -56,6 +57,16 @@ And you can then start sending requests with the client - for example:
5657
r = client.get("/v1/search?format=json&pageLength=2")
5758
r.json()
5859

60+
You can also use the scripts in the `./shell` directory to initialize a client. The following initializes a client
61+
that connects to this project's test application:
62+
63+
python -i shell/test_app.py
64+
65+
And this initializes a client that connects to the OOTB App-Services app server, which is used for examples in this
66+
project's documentation:
67+
68+
python -i shell/docs.py
69+
5970
## Testing the documentation locally
6071

6172
The docs for this project are stored in the `./docs` directory as a set of Markdown files. These are published via

docs/Gemfile.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ GEM
251251

252252
PLATFORMS
253253
arm64-darwin-21
254+
arm64-darwin-23
254255

255256
DEPENDENCIES
256257
github-pages (~> 228)

docs/eval.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
---
2+
layout: default
3+
title: Executing code
4+
nav_order: 7
5+
---
6+
7+
The [MarkLogic REST service extension](https://docs.marklogic.com/REST/client/service-extension) supports the
8+
execution of custom code, whether via an inline script or an existing module in your application's modules database.
9+
The MarkLogic Python client supports execution of custom code by simplifying the submission of custom code
10+
and converting the multipart response into more useful Python data types.
11+
12+
## Setup
13+
14+
The examples below all depend on the instructions in the [setup guide](example-setup.md) having already been performed.
15+
16+
To try out the examples, start a Python shell and first run the following:
17+
18+
```
19+
from marklogic import Client
20+
client = Client('http://localhost:8000', digest=('python-user', 'pyth0n'))
21+
```
22+
23+
## Executing ad-hoc queries
24+
25+
The [v1/eval REST endpoint](https://docs.marklogic.com/REST/POST/v1/eval) supports the execution of ad-hoc JavaScript
26+
and XQuery queries. Each type of query can be easily submitted via the client:
27+
28+
```
29+
client.eval(javascript="fn.currentDateTime()")
30+
client.eval(xquery="fn:current-dateTime()")
31+
```
32+
33+
Variables can optionally be provided via a `dict`:
34+
35+
```
36+
results = client.eval(javascript='Sequence.from([{"hello": myValue}])', vars={"myValue": "world"})
37+
assert "world" == results[0]["hello"]
38+
```
39+
40+
Because the REST endpoint returns a sequence of items, the client will always return a list of values. See the section
41+
below on how data types are converted to understand how the client will convert each value into an appropriate Python
42+
data type.
43+
44+
## Invoking modules
45+
46+
The [v1/invoke REST endpoint](https://docs.marklogic.com/REST/POST/v1/invoke) supports the execution of JavaScript
47+
and XQuery main modules that have been deployed to your application's modules database.
48+
49+
If you wish to attempt the examples below (instead of invoking your own modules), first run the following to
50+
insert a simple runnable module into the out-of-the-box "Modules" database:
51+
52+
```
53+
from marklogic.documents import Document
54+
module = Document('/sample.sjs', 'const doc = {"hello": "world"}; doc', permissions={"rest-reader": ["read", "update", "execute"]})
55+
client.documents.write(module, params={"database": "Modules"})
56+
```
57+
58+
A module can be invoked via the client in the following manner:
59+
60+
```
61+
# Set the input to the URI of the module you wish to invoke in your application's
62+
# modules database.
63+
client.invoke("/sample.sjs")
64+
```
65+
66+
You can provide variables to your module in the same fashion as when evaluating custom
67+
code (the variable will not have any impact on the sample module loaded above; this is
68+
shown purely to demonstrate how to define variables):
69+
70+
```
71+
client.invoke("/sample.sjs", vars={"my_var1": "value1"})
72+
```
73+
74+
## Conversion of data types
75+
76+
The REST endpoints for evaluating ad-hoc code and for invoking a module both return a sequence of values, with each
77+
value having MarkLogic-specific type information. The client will use this type information to convert each value into
78+
an appropriate Python data type. For example, each JSON object into the example below is converted into a `dict`:
79+
80+
```
81+
results = client.eval(javascript='Sequence.from([{"doc": 1}, {"doc": 2}])')
82+
assert len(results) == 2
83+
assert results[0]["doc"] == 1
84+
assert results[1]["doc"] == 2
85+
```
86+
87+
The following table describes how each MarkLogic type is associated with a Python data type. For any
88+
MarkLogic type not listed in the table, such as `hexBinary` and `base64Binary`, the value is not converted and will
89+
remain of type `bytes`.
90+
91+
| MarkLogic type | Python type |
92+
| --- | --- |
93+
| string | str |
94+
| integer | int |
95+
| boolean | bool |
96+
| decimal | [Decimal](https://docs.python.org/3/library/decimal.html) |
97+
| map | dict |
98+
| element() | str |
99+
| array | list |
100+
| array-node() | list |
101+
| object-node() | dict or `marklogic.documents.Document` |
102+
| document-node() | str or `marklogic.documents.Document` |
103+
| binary() | bytes or `marklogic.documents.Document` |
104+
105+
For the `object-node()`, `document-node()`, and `binary()` entries in the above table, a
106+
`marklogic.documents.Document` instance will be returned if the value is associated with a URI via
107+
the multipart `X-URI` header. Otherwise, a value of type `dict`, `str`, or `bytes` is returned respectively.
108+
109+
## Returning the original HTTP response
110+
111+
Each `client.eval` method and `client.invoke` accept a `return_response` argument. When that
112+
argument is set to `True`, the original response is returned. This can be useful for custom
113+
processing of the response or debugging requests.
114+
115+
## Referencing a transaction
116+
117+
The `client.eval` and `client.invoke` functions both support referencing a
118+
[REST API transaction](https://docs.marklogic.com/REST/client/transaction-management) via the `tx`
119+
argument. See [the guide on transactions](transactions.md) for further information.

docs/example-setup.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,30 @@ nav_order: 2
55
permalink: /setup
66
---
77

8-
The examples in this documentation depend on a particular MarkLogic username and password. If you
9-
would like to try these examples out against your own installation of MarkLogic, you will need to create this
10-
MarkLogic user. To do so, please go to the Admin application for your MarkLogic instance - e.g. if you are running MarkLogic locally, this will be at <http://localhost:8001> - and authenticate as your "admin" user.
11-
Then perform the following steps to create a new user:
8+
The examples in this documentation depend on a particular MarkLogic user with a role containing specific privileges.
9+
If you would like to try these examples out against your own installation of MarkLogic, you will need to create this
10+
MarkLogic user and role. To do so, please go to the Admin application for your MarkLogic instance - e.g. if you are
11+
running MarkLogic locally, this will be at <http://localhost:8001> - and authenticate as your "admin" user.
12+
Then perform the following steps to create a new role:
13+
14+
1. Click on "Roles" in the "Security" box.
15+
2. Click on "Create".
16+
3. In the form, enter `python-docs-role` for "Role Name".
17+
4. Scroll down and select the `rest-extension-user`, `rest-reader`, `rest-writer`, and `tde-admin` roles.
18+
5. Scroll further down and select the `xdbc:eval`, `xdbc:invoke`, and `xdmp:eval-in` privileges.
19+
6. Scroll to the top or bottom and click on "OK" to create the role.
20+
21+
After creating the role, return to the Admin application home page and perform the following steps:
1222

1323
1. Click on "Users" in the "Security" box.
1424
2. Click on "Create".
15-
3. In the form, enter "python-user" for "User Name" and "pyth0n" as the password.
16-
4. Scroll down until you see the "Roles" section. Click on the "rest-reader" and "rest-writer" checkboxes.
25+
3. In the form, enter `python-user` for "User Name" and `pyth0n` as the password.
26+
4. Scroll down until you see the "Roles" section and select the `python-docs-role` role.
1727
5. Scroll to the top or bottom and click on "OK" to create the user.
1828

29+
(Note that you could use the `admin` role instead to grant full access to all features in MarkLogic, but this is
30+
generally discouraged for security reasons.)
31+
1932
You can verify that you correctly created the user by accessing the REST API for the out-of-the-box REST API
2033
server in MarkLogic that listens on port 8000. Go to <http://localhost:8000/v1/search> (changing "localhost" to
2134
the correct name of your MarkLogic host if you are not running it locally) in a web browser and enter the

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ If you wish to try these examples on your own installation of MarkLogic, please
3131
for instructions on creating this user.
3232

3333
Otherwise, please see the [guide on creating a client](creating-client.md) for more information on connecting to a
34-
MarkLogic REST API instance. The [guide on managing documents](managing-documents/managing-documents.md) provides
35-
more information on how the client simplifies writing and reading multiple documents in a single request.
34+
MarkLogic REST API instance. Then choose a guide from the navigation on the left to see how the client can simplify
35+
your application's interactions with the MarkLogic REST API.
3636

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
layout: default
33
title: Managing documents
4-
nav_order: 3
4+
nav_order: 4
55
has_children: true
66
permalink: /documents
77
---
88

9-
The [/v1/documents endpoint](https://docs.marklogic.com/REST/client/management) in the MarkLogic REST API supports
9+
The [MarkLogic REST documents service](https://docs.marklogic.com/REST/client/management) supports
1010
operations that involve writing or reading a single document. It also supports operations that involve multiple
1111
documents, though those require use of a potentially complex multipart HTTP request or response. The MarkLogic Python
1212
client simplifies those operations by hiding the details of multipart requests and responses.

docs/managing-documents/reading.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,18 @@ print(docs)
114114
Please see [the application developer's guide](https://docs.marklogic.com/guide/rest-dev/documents#id_80116)
115115
for more information on reading documents.
116116

117+
## Returning the original HTTP response
118+
119+
Starting in the 1.1.0 release, the `client.documents.search` method accepts a
120+
`return_response` argument. When that argument is set to `True`, the original response
121+
is returned. This can be useful for custom processing of the response or debugging requests.
122+
123+
## Referencing a transaction
124+
125+
Starting in the 1.1.0 release, you can reference a
126+
[REST API transaction](https://docs.marklogic.com/REST/client/transaction-management) via the `tx`
127+
argument. See [the guide on transactions](../transactions.md) for further information.
128+
117129
## Error handling
118130

119131
If the `client.documents.read` method receives an HTTP response with a status code of 200, then the client will return

docs/managing-documents/searching.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ assert len(docs) == 2
155155
Please see [the application developer's guide](https://docs.marklogic.com/guide/rest-dev/search#id_49329)
156156
for more information on searching documents.
157157

158+
## Returning the original HTTP response
159+
160+
Starting in the 1.1.0 release, the `client.documents.search` method accepts a
161+
`return_response` argument. When that argument is set to `True`, the original response
162+
is returned. This can be useful for custom processing of the response or debugging requests.
163+
164+
## Referencing a transaction
165+
166+
Starting in the 1.1.0 release, you can reference a
167+
[REST API transaction](https://docs.marklogic.com/REST/client/transaction-management) via the `tx`
168+
argument. See [the guide on transactions](../transactions.md) for further information.
169+
158170
## Error handling
159171

160172
If the `client.documents.read` method receives an HTTP response with a status code of 200, then the client will return

docs/managing-documents/writing.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ response = client.documents.write(Document("/doc1.json", {"doc": 1}, permissions
150150
Please see [the application developer's guide](https://docs.marklogic.com/guide/rest-dev/documents#id_11953) for
151151
more information on writing documents.
152152

153+
## Referencing a transaction
154+
155+
Starting in the 1.1.0 release, you can reference a
156+
[REST API transaction](https://docs.marklogic.com/REST/client/transaction-management) via the `tx`
157+
argument. See [the guide on transactions](../transactions.md) for further information.
158+
159+
153160
## Error handling
154161

155162
Because the `client.documents.write` method returns a `requests Response` object, any error that occurs during

0 commit comments

Comments
 (0)