pandahub 0.3.11__zip → 0.3.13__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pandahub-0.3.11 → pandahub-0.3.13}/CHANGELOG.md +5 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/PKG-INFO +1 -1
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/variants.py +1 -1
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/PandaHub.py +50 -19
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/database_toolbox.py +44 -4
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub.egg-info/PKG-INFO +1 -1
- {pandahub-0.3.11 → pandahub-0.3.13}/pyproject.toml +1 -1
- {pandahub-0.3.11 → pandahub-0.3.13}/CONTRIBUTING.rst +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/LICENSE +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/MANIFEST.in +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/README.md +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/dependencies.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/internal/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/internal/db.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/internal/schemas.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/internal/settings.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/internal/toolbox.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/internal/users.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/main.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/auth.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/net.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/projects.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/timeseries.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/api/routers/users.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/datatypes.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/mongodb_indexes.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/timeseries/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/timeseries/data_sources/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/timeseries/data_sources/mongo_data.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub/lib/timeseries/output_writer_mongodb.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub.egg-info/SOURCES.txt +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub.egg-info/dependency_links.txt +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub.egg-info/requires.txt +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/pandahub.egg-info/top_level.txt +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/requirements.txt +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/setup.cfg +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/setup.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/__init__.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/conftest.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/performance_test.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/test_client.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/test_networks.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/test_projects.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/test/test_timeseries.py +0 -0
- {pandahub-0.3.11 → pandahub-0.3.13}/tutorials/config.py +0 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## [0.3.13]
|
|
4
|
+
- FIXED: fetching integer index on empty collection
|
|
5
|
+
- IMPROVED: context manager for mongo client /database / collection
|
|
6
|
+
- IMPROVED: project locking returns True if user already holds a lock on the project
|
|
7
|
+
|
|
3
8
|
## [0.3.11]
|
|
4
9
|
|
|
5
10
|
- IMPROVED: add lib.database_toolbox.get_mongo_client function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pandahub
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.13
|
|
4
4
|
Summary: Data hub for pandapower and pandapipes networks based on MongoDB
|
|
5
5
|
Author-email: Jan Ulffers <jan.ulffers@iee.fraunhofer.de>, Leon Thurner <leon.thurner@retoflow.de>, Jannis Kupka <jannis.kupka@retoflow.de>, Mike Vogt <mike.vogt@iee.fraunhofer.de>, Joschka Thurner <joschka.thurner@retoflow.de>, Alexander Scheidler <alexander.scheidler@iee.fraunhofer.de>
|
|
6
6
|
License: Copyright (c) 2022 by University of Kassel, Fraunhofer Institute for Energy Economics
|
|
@@ -22,7 +22,7 @@ class GetVariantsModel(BaseModel):
|
|
|
22
22
|
@router.post("/get_variants")
|
|
23
23
|
def get_variants(data: GetVariantsModel, ph=Depends(pandahub)):
|
|
24
24
|
ph.set_active_project_by_id(data.project_id)
|
|
25
|
-
variants_collection = ph.
|
|
25
|
+
variants_collection = ph.get_project_collection("variant")
|
|
26
26
|
|
|
27
27
|
variants = variants_collection.find({"net_id": data.net_id}, projection={"_id": 0})
|
|
28
28
|
return {variant.pop("index"): variant for variant in variants}
|
|
@@ -17,6 +17,8 @@ from functools import reduce
|
|
|
17
17
|
from operator import getitem
|
|
18
18
|
from uuid import UUID
|
|
19
19
|
from pymongo import MongoClient, ReplaceOne
|
|
20
|
+
from pymongo.database import Database
|
|
21
|
+
from pymongo.collection import Collection
|
|
20
22
|
from pymongo.errors import ServerSelectionTimeoutError, DuplicateKeyError
|
|
21
23
|
|
|
22
24
|
import pandapipes as pps
|
|
@@ -79,6 +81,7 @@ class PandaHub:
|
|
|
79
81
|
"read": ["owner", "developer", "guest"],
|
|
80
82
|
"write": ["owner", "developer"],
|
|
81
83
|
"user_management": ["owner"],
|
|
84
|
+
"delete_project": ["owner"],
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
# -------------------------
|
|
@@ -248,7 +251,7 @@ class PandaHub:
|
|
|
248
251
|
if project_id:
|
|
249
252
|
self.set_active_project_by_id(project_id)
|
|
250
253
|
project_id = self.active_project["_id"]
|
|
251
|
-
self.check_permission("
|
|
254
|
+
self.check_permission("delete_project")
|
|
252
255
|
if not i_know_this_action_is_final:
|
|
253
256
|
raise PandaHubError(
|
|
254
257
|
"Calling this function will delete the whole project and all the nets stored within. It can not be reversed. Add 'i_know_this_action_is_final=True' to confirm."
|
|
@@ -334,14 +337,23 @@ class PandaHub:
|
|
|
334
337
|
self.set_active_project(project_name, realm)
|
|
335
338
|
|
|
336
339
|
def lock_project(self):
|
|
337
|
-
|
|
338
|
-
result =
|
|
340
|
+
coll = self.mongo_client["user_management"]["projects"]
|
|
341
|
+
result = coll.find_one_and_update(
|
|
339
342
|
{
|
|
340
343
|
"_id": self.active_project["_id"],
|
|
344
|
+
"$or": [
|
|
345
|
+
{"locked": {"$eq": False}},
|
|
346
|
+
{
|
|
347
|
+
"$and": [
|
|
348
|
+
{"locked": {"$eq": True}},
|
|
349
|
+
{"locked_by": str(self.user_id)},
|
|
350
|
+
]
|
|
351
|
+
},
|
|
352
|
+
],
|
|
341
353
|
},
|
|
342
|
-
{"$set": {"locked": True, "locked_by": self.user_id}},
|
|
354
|
+
{"$set": {"locked": True, "locked_by": str(self.user_id)}},
|
|
343
355
|
)
|
|
344
|
-
return result
|
|
356
|
+
return result is not None
|
|
345
357
|
|
|
346
358
|
|
|
347
359
|
# def lock_project(self):
|
|
@@ -408,26 +420,42 @@ class PandaHub:
|
|
|
408
420
|
else:
|
|
409
421
|
return project_doc
|
|
410
422
|
|
|
411
|
-
def _get_project_database(self) ->
|
|
423
|
+
def _get_project_database(self) -> Database:
|
|
412
424
|
return self.get_project_database()
|
|
413
425
|
|
|
414
|
-
def get_project_database(self, collection: Optional[str] = None) ->
|
|
426
|
+
def get_project_database(self, collection: Optional[str] = None) -> Database:
|
|
427
|
+
"""
|
|
428
|
+
Get the database for the current active project.
|
|
429
|
+
|
|
430
|
+
Parameters
|
|
431
|
+
----------
|
|
432
|
+
collection or None
|
|
433
|
+
Name of document collection (DEPRECATED)
|
|
434
|
+
|
|
435
|
+
Returns
|
|
436
|
+
-------
|
|
437
|
+
pymongo.database.Database
|
|
438
|
+
"""
|
|
439
|
+
if collection is None:
|
|
440
|
+
return self.mongo_client[str(self.active_project["_id"])]
|
|
441
|
+
logger.warning(f"Passing a collection to get_project_database is deprecated. Use get_project_collection instead!")
|
|
442
|
+
return self.get_project_collection(collection)
|
|
443
|
+
|
|
444
|
+
def get_project_collection(self, collection_name: str) -> Collection:
|
|
415
445
|
"""
|
|
416
446
|
Get a MongoClient instance connected to the database for the current active project, optionally set to the given collection.
|
|
417
447
|
|
|
418
448
|
Parameters
|
|
419
449
|
----------
|
|
420
|
-
|
|
450
|
+
collection_name
|
|
421
451
|
Name of document collection
|
|
422
452
|
|
|
423
453
|
Returns
|
|
424
454
|
-------
|
|
425
|
-
|
|
455
|
+
pymongo.collection.Collection
|
|
426
456
|
"""
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return project_db
|
|
430
|
-
return project_db[collection]
|
|
457
|
+
return self.get_project_database()[collection_name]
|
|
458
|
+
|
|
431
459
|
|
|
432
460
|
def _get_global_database(self) -> MongoClient:
|
|
433
461
|
if (
|
|
@@ -460,7 +488,7 @@ class PandaHub:
|
|
|
460
488
|
"""
|
|
461
489
|
if not self.active_project:
|
|
462
490
|
raise PandaHubError("No project activated!")
|
|
463
|
-
return self.
|
|
491
|
+
return self.get_project_collection("_networks").find({}, {"_id:": 1}).distinct("_id")
|
|
464
492
|
|
|
465
493
|
def get_project_version(self):
|
|
466
494
|
return self.active_project.get("version", "0.2.2")
|
|
@@ -1750,14 +1778,14 @@ class PandaHub:
|
|
|
1750
1778
|
The value of the created index.
|
|
1751
1779
|
"""
|
|
1752
1780
|
query_filter = query_filter if query_filter is not None else {}
|
|
1753
|
-
coll = self.
|
|
1781
|
+
coll = self.get_project_collection(collection)
|
|
1754
1782
|
for retry in range(retries):
|
|
1755
1783
|
try:
|
|
1756
|
-
|
|
1784
|
+
max_index_doc = next(coll.find(query_filter, projection={index_field: 1})
|
|
1757
1785
|
.sort(index_field, -1)
|
|
1758
1786
|
.limit(1),
|
|
1759
1787
|
None)
|
|
1760
|
-
index = 0 if
|
|
1788
|
+
index = 0 if max_index_doc is None else int(max_index_doc[index_field]) + 1
|
|
1761
1789
|
coll.insert_one({index_field: index})
|
|
1762
1790
|
break
|
|
1763
1791
|
except DuplicateKeyError:
|
|
@@ -2674,7 +2702,10 @@ class PandaHub:
|
|
|
2674
2702
|
}
|
|
2675
2703
|
pipeline.append({"$project": projection})
|
|
2676
2704
|
if not include_metadata:
|
|
2677
|
-
|
|
2705
|
+
if compressed_ts_data:
|
|
2706
|
+
pipeline.append({"$project": {"timeseries_data": 1, "num_timestamps": 1}})
|
|
2707
|
+
else:
|
|
2708
|
+
pipeline.append({"$project": {"timeseries_data": 1}})
|
|
2678
2709
|
|
|
2679
2710
|
timeseries = []
|
|
2680
2711
|
for ts in db[collection_name].aggregate(pipeline):
|
|
@@ -2682,7 +2713,7 @@ class PandaHub:
|
|
|
2682
2713
|
continue
|
|
2683
2714
|
data = ts["timeseries_data"]
|
|
2684
2715
|
if compressed_ts_data:
|
|
2685
|
-
timeseries_data = decompress_timeseries_data(data, ts_format)
|
|
2716
|
+
timeseries_data = decompress_timeseries_data(data, ts_format, ts["num_timestamps"])
|
|
2686
2717
|
ts["timeseries_data"] = timeseries_data
|
|
2687
2718
|
else:
|
|
2688
2719
|
if ts_format == "timestamp_value":
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
from
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from collections.abc import Iterator
|
|
3
4
|
|
|
4
5
|
import numpy as np
|
|
5
6
|
import pandas as pd
|
|
6
7
|
from pymongo import MongoClient
|
|
8
|
+
from pymongo.database import Database
|
|
9
|
+
from pymongo.collection import Collection
|
|
7
10
|
|
|
8
11
|
from pandahub.api.internal.settings import MONGODB_URL, MONGODB_USER, MONGODB_PASSWORD
|
|
9
12
|
from pandahub.lib.datatypes import DATATYPES
|
|
@@ -188,7 +191,7 @@ def create_timeseries_document(timeseries,
|
|
|
188
191
|
document = add_timestamp_info_to_document(document, timeseries, ts_format)
|
|
189
192
|
document = {**document, **kwargs}
|
|
190
193
|
|
|
191
|
-
if
|
|
194
|
+
if "_id" not in document: # IDs set by users will not be overwritten
|
|
192
195
|
document["_id"] = get_document_hash(document)
|
|
193
196
|
|
|
194
197
|
if compress_ts_data:
|
|
@@ -425,8 +428,8 @@ def migrate_userdb_to_beanie(ph):
|
|
|
425
428
|
{'$out': 'users'}]
|
|
426
429
|
userdb.aggregate(migration)
|
|
427
430
|
|
|
428
|
-
def get_mongo_client(connection_url=MONGODB_URL, connection_user=MONGODB_USER,
|
|
429
|
-
connection_password=MONGODB_PASSWORD) -> MongoClient:
|
|
431
|
+
def get_mongo_client(connection_url: str = MONGODB_URL, connection_user: str = MONGODB_USER,
|
|
432
|
+
connection_password: str = MONGODB_PASSWORD) -> MongoClient:
|
|
430
433
|
mongo_client_args = {
|
|
431
434
|
"host": connection_url,
|
|
432
435
|
"uuidRepresentation": "standard",
|
|
@@ -438,3 +441,40 @@ def get_mongo_client(connection_url=MONGODB_URL, connection_user=MONGODB_USER,
|
|
|
438
441
|
"password": connection_password,
|
|
439
442
|
}
|
|
440
443
|
return MongoClient(**mongo_client_args)
|
|
444
|
+
|
|
445
|
+
@contextmanager
|
|
446
|
+
def mongo_client(database: str | None = None, collection: str | None = None, connection_url: str = MONGODB_URL,
|
|
447
|
+
connection_user: str = MONGODB_USER, connection_password: str = MONGODB_PASSWORD) -> Iterator[MongoClient | Database | Collection]:
|
|
448
|
+
"""Contextmanager for pymongo MongoClient / Database / Collection with close after use.
|
|
449
|
+
|
|
450
|
+
Parameters
|
|
451
|
+
----------
|
|
452
|
+
database: str or None
|
|
453
|
+
The database to connect to
|
|
454
|
+
collection: str or None
|
|
455
|
+
The collection to connect to
|
|
456
|
+
connection_url: str or None
|
|
457
|
+
Defaults to MONGODB_URL env var
|
|
458
|
+
connection_user: str or None
|
|
459
|
+
Defaults to MONGODB_USER env var
|
|
460
|
+
connection_password: str or None
|
|
461
|
+
Defaults to MONGODB_PASSWORD env var
|
|
462
|
+
|
|
463
|
+
Returns
|
|
464
|
+
-------
|
|
465
|
+
Contextmanager yielding MongoClient / Database / Collection
|
|
466
|
+
"""
|
|
467
|
+
if collection is not None and database is None:
|
|
468
|
+
raise ValueError("Must specify database to access a collection!")
|
|
469
|
+
client = get_mongo_client(connection_url, connection_user, connection_password)
|
|
470
|
+
try:
|
|
471
|
+
if database is not None and collection is not None:
|
|
472
|
+
yield client[database][collection]
|
|
473
|
+
elif database is not None:
|
|
474
|
+
yield client[database]
|
|
475
|
+
else:
|
|
476
|
+
yield client
|
|
477
|
+
finally:
|
|
478
|
+
client.close()
|
|
479
|
+
|
|
480
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pandahub
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.13
|
|
4
4
|
Summary: Data hub for pandapower and pandapipes networks based on MongoDB
|
|
5
5
|
Author-email: Jan Ulffers <jan.ulffers@iee.fraunhofer.de>, Leon Thurner <leon.thurner@retoflow.de>, Jannis Kupka <jannis.kupka@retoflow.de>, Mike Vogt <mike.vogt@iee.fraunhofer.de>, Joschka Thurner <joschka.thurner@retoflow.de>, Alexander Scheidler <alexander.scheidler@iee.fraunhofer.de>
|
|
6
6
|
License: Copyright (c) 2022 by University of Kassel, Fraunhofer Institute for Energy Economics
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pandahub"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.13" # File format version '__format_version__' is tracked in __init__.py
|
|
8
8
|
authors=[
|
|
9
9
|
{ name = "Jan Ulffers", email = "jan.ulffers@iee.fraunhofer.de" },
|
|
10
10
|
{ name = "Leon Thurner", email = "leon.thurner@retoflow.de" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|