pandahub 0.3.12__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.
Files changed (49) hide show
  1. {pandahub-0.3.12 → pandahub-0.3.13}/CHANGELOG.md +5 -0
  2. {pandahub-0.3.12 → pandahub-0.3.13}/PKG-INFO +1 -1
  3. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/variants.py +1 -1
  4. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/PandaHub.py +43 -16
  5. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/database_toolbox.py +44 -4
  6. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub.egg-info/PKG-INFO +1 -1
  7. {pandahub-0.3.12 → pandahub-0.3.13}/pyproject.toml +1 -1
  8. {pandahub-0.3.12 → pandahub-0.3.13}/CONTRIBUTING.rst +0 -0
  9. {pandahub-0.3.12 → pandahub-0.3.13}/LICENSE +0 -0
  10. {pandahub-0.3.12 → pandahub-0.3.13}/MANIFEST.in +0 -0
  11. {pandahub-0.3.12 → pandahub-0.3.13}/README.md +0 -0
  12. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/__init__.py +0 -0
  13. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/__init__.py +0 -0
  14. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/dependencies.py +0 -0
  15. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/internal/__init__.py +0 -0
  16. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/internal/db.py +0 -0
  17. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/internal/schemas.py +0 -0
  18. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/internal/settings.py +0 -0
  19. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/internal/toolbox.py +0 -0
  20. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/internal/users.py +0 -0
  21. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/main.py +0 -0
  22. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/__init__.py +0 -0
  23. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/auth.py +0 -0
  24. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/net.py +0 -0
  25. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/projects.py +0 -0
  26. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/timeseries.py +0 -0
  27. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/api/routers/users.py +0 -0
  28. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/__init__.py +0 -0
  29. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/datatypes.py +0 -0
  30. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/mongodb_indexes.py +0 -0
  31. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/timeseries/__init__.py +0 -0
  32. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/timeseries/data_sources/__init__.py +0 -0
  33. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/timeseries/data_sources/mongo_data.py +0 -0
  34. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub/lib/timeseries/output_writer_mongodb.py +0 -0
  35. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub.egg-info/SOURCES.txt +0 -0
  36. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub.egg-info/dependency_links.txt +0 -0
  37. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub.egg-info/requires.txt +0 -0
  38. {pandahub-0.3.12 → pandahub-0.3.13}/pandahub.egg-info/top_level.txt +0 -0
  39. {pandahub-0.3.12 → pandahub-0.3.13}/requirements.txt +0 -0
  40. {pandahub-0.3.12 → pandahub-0.3.13}/setup.cfg +0 -0
  41. {pandahub-0.3.12 → pandahub-0.3.13}/setup.py +0 -0
  42. {pandahub-0.3.12 → pandahub-0.3.13}/test/__init__.py +0 -0
  43. {pandahub-0.3.12 → pandahub-0.3.13}/test/conftest.py +0 -0
  44. {pandahub-0.3.12 → pandahub-0.3.13}/test/performance_test.py +0 -0
  45. {pandahub-0.3.12 → pandahub-0.3.13}/test/test_client.py +0 -0
  46. {pandahub-0.3.12 → pandahub-0.3.13}/test/test_networks.py +0 -0
  47. {pandahub-0.3.12 → pandahub-0.3.13}/test/test_projects.py +0 -0
  48. {pandahub-0.3.12 → pandahub-0.3.13}/test/test_timeseries.py +0 -0
  49. {pandahub-0.3.12 → 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.12
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.get_project_database("variant")
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
@@ -335,14 +337,23 @@ class PandaHub:
335
337
  self.set_active_project(project_name, realm)
336
338
 
337
339
  def lock_project(self):
338
- db = self.mongo_client["user_management"]["projects"]
339
- result = db.update_one(
340
+ coll = self.mongo_client["user_management"]["projects"]
341
+ result = coll.find_one_and_update(
340
342
  {
341
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
+ ],
342
353
  },
343
- {"$set": {"locked": True, "locked_by": self.user_id}},
354
+ {"$set": {"locked": True, "locked_by": str(self.user_id)}},
344
355
  )
345
- return result.acknowledged and result.modified_count > 0
356
+ return result is not None
346
357
 
347
358
 
348
359
  # def lock_project(self):
@@ -409,26 +420,42 @@ class PandaHub:
409
420
  else:
410
421
  return project_doc
411
422
 
412
- def _get_project_database(self) -> MongoClient:
423
+ def _get_project_database(self) -> Database:
413
424
  return self.get_project_database()
414
425
 
415
- def get_project_database(self, collection: Optional[str] = None) -> MongoClient:
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:
416
445
  """
417
446
  Get a MongoClient instance connected to the database for the current active project, optionally set to the given collection.
418
447
 
419
448
  Parameters
420
449
  ----------
421
- collection
450
+ collection_name
422
451
  Name of document collection
423
452
 
424
453
  Returns
425
454
  -------
426
- MongoClient
455
+ pymongo.collection.Collection
427
456
  """
428
- project_db = self.mongo_client[str(self.active_project["_id"])]
429
- if collection is None:
430
- return project_db
431
- return project_db[collection]
457
+ return self.get_project_database()[collection_name]
458
+
432
459
 
433
460
  def _get_global_database(self) -> MongoClient:
434
461
  if (
@@ -461,7 +488,7 @@ class PandaHub:
461
488
  """
462
489
  if not self.active_project:
463
490
  raise PandaHubError("No project activated!")
464
- return self.get_project_database("_networks").find({}, {"_id:": 1}).distinct("_id")
491
+ return self.get_project_collection("_networks").find({}, {"_id:": 1}).distinct("_id")
465
492
 
466
493
  def get_project_version(self):
467
494
  return self.active_project.get("version", "0.2.2")
@@ -1751,14 +1778,14 @@ class PandaHub:
1751
1778
  The value of the created index.
1752
1779
  """
1753
1780
  query_filter = query_filter if query_filter is not None else {}
1754
- coll = self.get_project_database(collection)
1781
+ coll = self.get_project_collection(collection)
1755
1782
  for retry in range(retries):
1756
1783
  try:
1757
- max_index = next(coll.find(query_filter, projection={index_field: 1})
1784
+ max_index_doc = next(coll.find(query_filter, projection={index_field: 1})
1758
1785
  .sort(index_field, -1)
1759
1786
  .limit(1),
1760
1787
  None)
1761
- index = 0 if max_index is None else int(max_index[0][index_field]) + 1
1788
+ index = 0 if max_index_doc is None else int(max_index_doc[index_field]) + 1
1762
1789
  coll.insert_one({index_field: index})
1763
1790
  break
1764
1791
  except DuplicateKeyError:
@@ -1,9 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Optional
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 not "_id" in document: # IDs set by users will not be overwritten
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.12
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.12" # File format version '__format_version__' is tracked in __init__.py
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