Skip to content

Commit

Permalink
Add User client (#470)
Browse files Browse the repository at this point in the history
* update generated client and add tests
* add user module with example and docs
* add changelog entry and fix other PR numbers
* Merge remote-tracking branch 'origin/master' into user-client
* Update Changelog.md
  • Loading branch information
jstriebel authored Nov 1, 2021
1 parent 73b6290 commit 7ce4e56
Show file tree
Hide file tree
Showing 43 changed files with 2,325 additions and 118 deletions.
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ nav:
- webknossos-py/examples/upload_image_data.md
- webknossos-py/examples/learned_segmenter.md
- webknossos-py/examples/skeleton_synapse_candidates.md
- webknossos-py/examples/user_times.md
- API Reference:
- Geometry:
- BoundingBox: api/webknossos/geometry/bounding_box.md
Expand Down
1 change: 1 addition & 0 deletions docs/src/webknossos-py/examples/learned_segmenter.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This example trains a segmenter from a volume annotation and applies it to the w
It builds upon the two previous examples using the [Dataset API](dataset_usage.md) and [dataset upload](upload_image_data.md).
Additionally, it downloads [this manual volume annotation of a subset of the skin example dataset](https://webknossos.org/annotations/Explorational/616457c2010000870032ced4) which is used for training.

*This example additionally needs the scikit-learn package.*

```python
--8<--
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Skeleton Synapse Candidates

This example uses `open_nml` to produce an instance of the [`Skeleton`](../../api/webknossos/skeleton/skeleton.md) class and manipulates it:
This example uses `open_nml` to produce an instance of the [`Skeleton`](../../api/webknossos/skeleton/skeleton.md#Skeleton) class and manipulates it:

```python
--8<--
Expand Down
2 changes: 1 addition & 1 deletion docs/src/webknossos-py/examples/upload_image_data.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Upload Image Data

Loads the [cell dataset](https://scikit-image.org/docs/dev/api/skimage.data.html#skimage.data.cell), writes it into a [wkw Dataset](../../api/webknossos/dataset/dataset.md) and uploads it to a local webknossos instance using [`webknossos_context`](http://localhost:8197/api/webknossos/client/context.html#webknossos_context).
Loads the [cell dataset](https://scikit-image.org/docs/dev/api/skimage.data.html#skimage.data.cell), writes it into a [wkw Dataset](../../api/webknossos/dataset/dataset.md) and uploads it to a local webknossos instance using [`webknossos_context`](../../api/webknossos/client/context.md#webknossos_context).

```python
--8<--
Expand Down
27 changes: 27 additions & 0 deletions docs/src/webknossos-py/examples/user_times.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Logged User Times

This example uses the [`User` class](../../api/webknossos/client/user.md#User) to load the logged times
for all users of whom the current user is admin or team-manager.

*This example additionally needs the pandas and tabulate packages.*

```python
--8<--
webknossos/examples/user_times.py
--8<--
```

This results in an output similar to

```
Logged User Times 2021:
| email | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|:-----------------------|-----:|-----:|-----:|-----:|----:|----:|----:|
| [email protected] | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| [email protected] | 0 | 0 | 16 | 210 | 0 | 271 | 150 |
| [email protected] | 0 | 0 | 553 | 0 | 0 | 0 | 0 |
| [email protected] | 0 | 0 | 0 | 1746 | 0 | 0 | 486 |
| [email protected] | 36 | 0 | 158 | 0 | 20 | 0 | 452 |
| [email protected] | 0 | 260 | 674 | 903 | 0 | 541 | 0 |
```
9 changes: 6 additions & 3 deletions webknossos/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ For upgrade instructions, please check the respective *Breaking Changes* section
[Commits](https://github.com/scalableminds/webknossos-cuber/compare/v0.8.18...HEAD)

### Breaking Changes
- `BoundingBox.chunk()`'s 2nd parameter `chunk_border_alignments` now does not accept a list with a single `int` anymore. [#437](https://github.com/scalableminds/webknossos-libs/pull/452)
- `BoundingBox.chunk()`'s 2nd parameter `chunk_border_alignments` now does not accept a list with a single `int` anymore. [#452](https://github.com/scalableminds/webknossos-libs/pull/452)

### Added
- Added a new Annotation class which includes skeletons as well as volume-annotations. [#437](https://github.com/scalableminds/webknossos-libs/pull/452)
- Added dataset down- and upload as well as annotation download, see the examples `learned_segmenter.py` and `upload_image_data.py`. [#437](https://github.com/scalableminds/webknossos-libs/pull/452)
- Added a new Annotation class which includes skeletons as well as volume-annotations. [#452](https://github.com/scalableminds/webknossos-libs/pull/452)
- Added dataset down- and upload as well as annotation download, see the examples `learned_segmenter.py` and `upload_image_data.py`. [#452](https://github.com/scalableminds/webknossos-libs/pull/452)
- Added a `User` class to the client that can be used to get meta-information of users or their logged time. The currently logged in user can be accessed, as well as all managed users. [#470](https://github.com/scalableminds/webknossos-libs/pull/470)

### Changed
- `View`s now always open the `wkw.Dataset` lazily. All explicit calls to `View.open()` and `View.close()` must be removed. [#448](https://github.com/scalableminds/webknossos-libs/pull/448)
- Removed the `organization` parameter from the `webknossos_context` function. The organization will automatically be fetched using the token of the user. [#470](https://github.com/scalableminds/webknossos-libs/pull/470)

### Fixed
- Make Views picklable. We now ignore the file handle when we pickle Views. [#469](https://github.com/scalableminds/webknossos-libs/pull/469)

Expand Down
26 changes: 23 additions & 3 deletions webknossos/__generate_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def generate_client(openapi_schema: Dict) -> None:
with NamedTemporaryFile("w", suffix=".json") as schema_file:
schema_file.write(json.dumps(openapi_schema))
generator_config = Config(
project_name_override="webknossos/client/generated",
project_name_override="webknossos/client/_generated",
package_name_override=".",
)
generator_project = _get_project_for_url_or_path(
Expand Down Expand Up @@ -62,8 +62,12 @@ def iterate_request_ids_with_responses() -> Iterable[Tuple[str, bytes]]:
from webknossos.client._generated.api.default import (
annotation_info,
build_info,
current_user_info,
dataset_info,
datastore_list,
generate_token_for_data_store,
user_list,
user_logged_time,
)

d = datetime.utcnow()
Expand All @@ -87,16 +91,32 @@ def iterate_request_ids_with_responses() -> Iterable[Tuple[str, bytes]]:
assert dataset_info_response.status_code == 200
yield "datasetInfo", dataset_info_response.content

for api_endpoint in [datastore_list, build_info]:
for api_endpoint in [
datastore_list,
build_info,
current_user_info,
generate_token_for_data_store,
user_list,
]:
api_endpoint_name = api_endpoint.__name__.split(".")[-1]
api_endpoint_name = snake_to_camel_case(api_endpoint_name)

api_endpoint_response = api_endpoint.sync_detailed(client=client)
assert api_endpoint_response.status_code == 200
yield api_endpoint_name, api_endpoint_response.content

if api_endpoint == current_user_info:
user_id = json.loads(api_endpoint_response.content)["id"]

user_logged_time_response = user_logged_time.sync_detailed(
id=user_id,
client=client,
)
assert user_logged_time_response.status_code == 200
yield "userLoggedTime", user_logged_time_response.content


FIELDS_WITH_VARYING_CONTENT = ["adminViewConfiguration"]
FIELDS_WITH_VARYING_CONTENT = ["adminViewConfiguration", "novelUserExperienceInfos"]


def make_properties_required(x: Any) -> None:
Expand Down
23 changes: 23 additions & 0 deletions webknossos/examples/user_times.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pandas as pd

import webknossos as wk

df = pd.DataFrame()
df.columns = pd.MultiIndex([[], []], [[], []], names=("year", "month"))
df.index.name = "email"

users = wk.User.get_all_managed_users()
for user in users:
for logged_time in user.get_logged_times():
df.loc[
user.email, (logged_time.year, logged_time.month)
] = logged_time.duration_in_seconds

df = df.fillna(0).astype("uint")
df = df.sort_index(axis="index").sort_index(axis="columns")

year = 2021
has_logged_times_in_year = df.loc[:, year].sum(axis="columns") != 0

print(f"Logged User Times {year}:\n")
print(df.loc[has_logged_times_in_year, year].to_markdown())
75 changes: 73 additions & 2 deletions webknossos/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webknossos/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ readme = "README.md"
license = "AGPL-3.0"

[tool.poetry.dependencies]
python = "^3.7"
python = "^3.7,>=3.7.1"
attrs = "^21.1.0"
boltons = "~21.0.0"
cattrs = "1.7.1"
Expand All @@ -33,9 +33,11 @@ inducoapi = "2.0.0"
isort = "^5.9.3"
mypy = "0.910"
openapi-python-client = "0.10.3"
pandas = "^1.3.4"
pylint = "^2.10.2"
pytest = "^6.2.4"
pytest-recording = "^0.12.0"
tabulate = "^0.8.9"
types-python-dateutil = "^0.1.6"

[tool.black]
Expand Down
Loading

0 comments on commit 7ce4e56

Please sign in to comment.