From a70893c8339dfb742038eca8d095e56126ee1af4 Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:32:41 -0800 Subject: [PATCH 01/10] add precommit and fix formatting --- .github/workflows/pre-commit.yaml | 38 + .github/workflows/release.yaml | 4 +- .pre-commit-config.yaml | 51 + LICENSE.txt | 4 +- MANIFEST.in | 2 +- Makefile | 2 +- README.md | 2 +- btrdbextras/__init__.py | 2 +- btrdbextras/conn.py | 8 +- btrdbextras/dq.py | 102 +- btrdbextras/eventproc/__init__.py | 11 +- btrdbextras/eventproc/eventproc.py | 108 +- btrdbextras/eventproc/protobuff/api_pb2.py | 1481 ++++++++++------- .../eventproc/protobuff/api_pb2_grpc.py | 238 +-- docs/source/conf.py | 23 +- docs/source/eventproc.rst | 2 +- docs/source/installing.rst | 1 - release.sh | 2 +- requirements.txt | 2 +- setup.cfg | 58 + setup.py | 75 +- tests/requirements.txt | 2 +- tests/test_base.py | 7 +- 23 files changed, 1436 insertions(+), 789 deletions(-) create mode 100644 .github/workflows/pre-commit.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 setup.cfg diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..858e465 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,38 @@ +name: pre-commit + +on: + pull_request: + branches: + - master + types: + - opened + - reopened + - ready_for_review + - synchronize + +env: + SKIP: pytest-check + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 # get full git history + - uses: actions/setup-python@v3 + with: + cache: 'pip' + - name: Install pre-commit + run: | + pip install pre-commit + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v21 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run pre-commit + uses: pre-commit/action@v2.0.3 + with: + extra_args: --files ${{ steps.changed-files.outputs.all_changed_files }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 87de83e..09c37a5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.6, 3.7, 3.8] + python-version: ["3.8", "3.9", "3.10", "3.11"] os: [ubuntu-latest, macos-latest, windows-latest] steps: @@ -75,4 +75,4 @@ jobs: uses: pypa/gh-action-pypi-publish@master with: user: __token__ - password: ${{ secrets.PYPI_DEPLOYMENT_TOKEN }} \ No newline at end of file + password: ${{ secrets.PYPI_DEPLOYMENT_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c62cb0d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,51 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + exclude: setup.cfg +- repo: https://github.com/psf/black + rev: 23.3.0 + hooks: + - id: black-jupyter + args: [--line-length=88] +- repo: https://github.com/pycqa/isort + rev: 5.11.5 + hooks: + - id: isort + name: isort (python) + args: [--profile=black, --line-length=88] +- repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: # Enforce that python3.6+ type annotations are used instead of type comments + - id: python-use-type-annotations +- repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 +# args: [] +#- repo: https://github.com/PyCQA/pydocstyle +# rev: 6.1.1 +# hooks: +# - id: pydocstyle +- repo: https://github.com/kynan/nbstripout + rev: 0.6.1 + hooks: + - id: nbstripout + name: nbstripout + description: 'nbstripout: strip output from Jupyter and IPython notebooks' + entry: nbstripout + language: python + types: [jupyter] + files: kinesis/dominion_apps/ # Run only on notebooks in dominion_apps directory + # exclude: # add files here to keep output cells in Jupyter during commit +- repo: local + hooks: + - id: pytest-check + name: pytest-check + entry: pytest + language: system + pass_filenames: false + always_run: true diff --git a/LICENSE.txt b/LICENSE.txt index e07e178..87f9ad8 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -6,6 +6,6 @@ Redistribution and use in source and binary forms, with or without modification, 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in index cd0cdb5..99d1fdb 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -19,4 +19,4 @@ global-exclude *.py[co] global-exclude .ipynb_checkpoints global-exclude .DS_Store global-exclude .env -global-exclude .coverage.* \ No newline at end of file +global-exclude .coverage.* diff --git a/Makefile b/Makefile index 489fafa..e80d39d 100644 --- a/Makefile +++ b/Makefile @@ -59,4 +59,4 @@ deploy: # Build html version of docs html: - $(SPHINXBUILD) -b html $(SPHINXOPTS) $(SPHINXSOURCEDIR) $(SPHINXBUILDDIR) \ No newline at end of file + $(SPHINXBUILD) -b html $(SPHINXOPTS) $(SPHINXSOURCEDIR) $(SPHINXBUILDDIR) diff --git a/README.md b/README.md index 7cf7bac..3c544c5 100644 --- a/README.md +++ b/README.md @@ -43,4 +43,4 @@ Note that the documentation also requires Sphix and other dependencies to succes ## Versioning -This codebases uses a form of [Semantic Versioning](http://semver.org/) to structure version numbers. In general, the major version number will track with the BTrDB codebase to transparently maintain version compatibility. Planned features between major versions will increment the minor version while any special releases (bug fixes, etc.) will increment the patch number. \ No newline at end of file +This codebases uses a form of [Semantic Versioning](http://semver.org/) to structure version numbers. In general, the major version number will track with the BTrDB codebase to transparently maintain version compatibility. Planned features between major versions will increment the minor version while any special releases (bug fixes, etc.) will increment the patch number. diff --git a/btrdbextras/__init__.py b/btrdbextras/__init__.py index 5a9dad2..5e701f5 100644 --- a/btrdbextras/__init__.py +++ b/btrdbextras/__init__.py @@ -1,5 +1,5 @@ from .conn import Connection -__version__ = 'v5.11.9' +__version__ = "v5.11.9" __all__ = ["__version__", "Connection"] diff --git a/btrdbextras/conn.py b/btrdbextras/conn.py index 506dfb3..da2ad8c 100644 --- a/btrdbextras/conn.py +++ b/btrdbextras/conn.py @@ -21,9 +21,13 @@ ## Classes ########################################################################## -class Connection(): - def __init__(self, endpoint=os.environ.get("BTRDB_ENDPOINTS"), apikey=os.environ.get("BTRDB_API_KEY")): +class Connection: + def __init__( + self, + endpoint=os.environ.get("BTRDB_ENDPOINTS"), + apikey=os.environ.get("BTRDB_API_KEY"), + ): if endpoint is None or endpoint.strip() == "": raise ValueError("invalid endpoint or BTRDB_ENDPOINTS env variable not set") diff --git a/btrdbextras/dq.py b/btrdbextras/dq.py index 75bcd0c..6dfc141 100644 --- a/btrdbextras/dq.py +++ b/btrdbextras/dq.py @@ -1,21 +1,24 @@ import re import warnings -from tabulate import tabulate import btrdb -from btrdb.stream import StreamSet, Stream +from btrdb.stream import Stream, StreamSet from btrdb.utils.general import pointwidth from btrdb.utils.timez import ns_delta, to_nanoseconds +from tabulate import tabulate KNOWN_DISTILLER_TYPES = ["repeats", "duplicate-times", "zeros"] + class AmbiguousDistillateError(ValueError): """ Raised when a distillate stream's name contains references to multiple known data quality distiller names """ + pass + class DQDistillate(Stream): """ Subsets a Stream object and allows for identfication of data quality events @@ -24,21 +27,26 @@ class DQDistillate(Stream): ---------- btrdb : BTrDB A reference to the BTrDB object connecting this stream back to the - physical server. + physical server. uuid : UUID The unique UUID identifier for this stream. """ + def __init__(self, btrdb, uu): # gives all same attrs/methods as Stream super().__init__(btrdb, uu) - # NOTE: this involves determining distiller type based on the distillate + # NOTE: this involves determining distiller type based on the distillate # stream name, so we will need to be careful how we name distillates - types = re.findall(r"(?=("+'|'.join(KNOWN_DISTILLER_TYPES)+r"))", self.name) + types = re.findall(r"(?=(" + "|".join(KNOWN_DISTILLER_TYPES) + r"))", self.name) if len(types) == 0: - raise ValueError(f"unknown distiller type. Must be one of [{', '.join(KNOWN_DISTILLER_TYPES)}]") + raise ValueError( + f"unknown distiller type. Must be one of [{', '.join(KNOWN_DISTILLER_TYPES)}]" + ) if len(types) > 1: - raise AmbiguousDistillateError(f"ambiguous distiller name. contains references to [{', '.join(types)}]") + raise AmbiguousDistillateError( + f"ambiguous distiller name. contains references to [{', '.join(types)}]" + ) self.type = types[0] def contains_issue(self, start=None, end=None, depth=30): @@ -69,7 +77,7 @@ def contains_issue(self, start=None, end=None, depth=30): if end is None: latest = self.latest() # adding 1 to end time because end is exclusive in windows() - end = latest[0].time +1 if latest else None + end = latest[0].time + 1 if latest else None start, end = to_nanoseconds(start), to_nanoseconds(end) # There's no event if there's no data @@ -82,6 +90,7 @@ def contains_issue(self, start=None, end=None, depth=30): def __repr__(self): return f"DQDistillate collection={self.collection}, name={self.name}, type={self.type}" + class DQStream(Stream): """ Subsets Stream object. Contains a regular BTrDB stream along with its distillate Streams @@ -90,11 +99,12 @@ class DQStream(Stream): ---------- stream: btrdb.stream.Stream """ + def __init__(self, stream): # gives all same attrs/methods as Stream super().__init__(stream._btrdb, stream.uuid) self._distillates = self._get_distillates() - + def _get_distillates(self): """ Finds distillate Streams for each of the underlying source Streams @@ -107,7 +117,9 @@ def _get_distillates(self): # NOTE: This involves looking up distillate streams by their source_uuid annotation, so we # need to make sure that all distillers give output streams this annotation distillates = [] - for stream in self._btrdb.streams_in_collection(annotations={"source_uuid": str(self.uuid)}): + for stream in self._btrdb.streams_in_collection( + annotations={"source_uuid": str(self.uuid)} + ): try: distillates.append(DQDistillate(stream._btrdb, stream.uuid)) # we only want to raise this error if we aren't sure which distiller the stream is @@ -118,16 +130,18 @@ def _get_distillates(self): else: continue if len(distillates) < 1: - warnings.warn(f"Could not find any data quality distillates for stream {str(self.uuid)}") + warnings.warn( + f"Could not find any data quality distillates for stream {str(self.uuid)}" + ) return distillates - + @property def distillates(self): """ Returns list of distillate Streams """ return self._distillates - + def list_distillates(self): """ Outputs dict that shows which distillates the DQStream has available @@ -144,8 +158,8 @@ def list_distillates(self): "name": self.name, } distillers = { - distiller: True if self[distiller] - else False for distiller in KNOWN_DISTILLER_TYPES + distiller: True if self[distiller] else False + for distiller in KNOWN_DISTILLER_TYPES } # combine basic info with distiller info return {**info, **distillers} @@ -163,7 +177,7 @@ def contains_any_issue(self, start=None, end=None, depth=30): depth: (optional) int The precision of the window duration as a power of 2 in nanoseconds. e.g 30 would make the window duration accurate to roughly 1 second - + Returns ------- bool @@ -192,7 +206,7 @@ def contains_issue(self, distil_type, start=None, end=None, depth=30): depth: (optional) int The precision of the window duration as a power of 2 in nanoseconds. e.g 30 would make the window duration accurate to roughly 1 second - + Returns ------- bool @@ -204,7 +218,7 @@ def contains_issue(self, distil_type, start=None, end=None, depth=30): except KeyError: return None return distillate.contains_issue(start=start, end=end, depth=depth) - + def __getitem__(self, item): for distillate in self._distillates: if distillate.type == item: @@ -213,7 +227,8 @@ def __getitem__(self, item): def __repr__(self): return f"DQStream collection={self.collection}, name={self.name}" - + + class DQStreamSet(StreamSet): """ Subsets a StreamSet object. Contains a list of Streams along with each of their @@ -224,7 +239,8 @@ class DQStreamSet(StreamSet): streams: list list[btrdb.stream.Stream] """ - def __init__(self, streams): + + def __init__(self, streams): dq_streams = [] for stream in streams: if not isinstance(stream, DQStream): @@ -259,12 +275,21 @@ def describe(self, notebook=False, *additional_cols): KNOWN_TAGS = ["name", "unit", "ingress", "distiller"] contains_annotations = False - table = [["Collection", "Name", "Unit", "UUID", "Version", "Available Data Quality Info"]] + table = [ + [ + "Collection", + "Name", + "Unit", + "UUID", + "Version", + "Available Data Quality Info", + ] + ] # add args as table columns if user provides them if additional_cols: if not all(a in KNOWN_TAGS for a in additional_cols): - contains_annotations=True + contains_annotations = True table[0].extend(additional_cols) # query for metadata for all streams upfront @@ -273,7 +298,10 @@ def describe(self, notebook=False, *additional_cols): uu_str = ",".join(f"'{uu}'" for uu in uuids) if not contains_annotations: query = f"SELECT uuid, name, unit, distiller, ingress FROM streams WHERE uuid IN ({uu_str})" - meta = {res["uuid"]: {tag: res.get(tag) for tag in KNOWN_TAGS} for res in self._conn.query(query)} + meta = { + res["uuid"]: {tag: res.get(tag) for tag in KNOWN_TAGS} + for res in self._conn.query(query) + } else: query = f""" SELECT uuid, annotations, name, unit, distiller, ingress @@ -281,9 +309,12 @@ def describe(self, notebook=False, *additional_cols): WHERE uuid IN ({uu_str}) """ meta = { - res["uuid"]: {**res["annotations"], **{tag: res.get(tag) for tag in KNOWN_TAGS}} - for res in self._conn.query(query) - } + res["uuid"]: { + **res["annotations"], + **{tag: res.get(tag) for tag in KNOWN_TAGS}, + } + for res in self._conn.query(query) + } # iterate through streams, lookup metadata by uuid for stream in self._streams: @@ -319,10 +350,7 @@ def list_distillates(self): as well as bool values for each distiller that denote which distillates are available to the DQStream """ - return [ - stream.list_distillates() - for stream in self._streams - ] + return [stream.list_distillates() for stream in self._streams] def contains_any_issue(self, start=None, end=None, depth=30): """ @@ -337,7 +365,7 @@ def contains_any_issue(self, start=None, end=None, depth=30): depth: (optional) int The precision of the window duration as a power of 2 in nanoseconds. e.g 30 would make the window duration accurate to roughly 1 second - + Returns ------- dict[str, bool] @@ -345,7 +373,9 @@ def contains_any_issue(self, start=None, end=None, depth=30): contain any event """ return { - str(stream.uuid): stream.contains_any_issue(start=start, end=end, depth=depth) + str(stream.uuid): stream.contains_any_issue( + start=start, end=end, depth=depth + ) for stream in self._streams } @@ -364,7 +394,7 @@ def contains_issue(self, distil_type, start=None, end=None, depth=30): depth: (optional) int The precision of the window duration as a power of 2 in nanoseconds. e.g 30 would make the window duration accurate to roughly 1 second - + Returns ------- dict[str, bool] @@ -372,10 +402,12 @@ def contains_issue(self, distil_type, start=None, end=None, depth=30): a certain event """ return { - str(stream.uuid): stream.contains_issue(distil_type, start=start, end=end, depth=depth) + str(stream.uuid): stream.contains_issue( + distil_type, start=start, end=end, depth=depth + ) for stream in self._streams } - + def __getitem__(self, index): """ Returns the DQStream contained at a given index within the set diff --git a/btrdbextras/eventproc/__init__.py b/btrdbextras/eventproc/__init__.py index ae8d7e7..ddc489b 100644 --- a/btrdbextras/eventproc/__init__.py +++ b/btrdbextras/eventproc/__init__.py @@ -1,3 +1,10 @@ -from .eventproc import hooks, list_handlers, register, deregister, upload_file, _uploads +from .eventproc import _uploads, deregister, hooks, list_handlers, register, upload_file -__all__ = ['hooks', 'list_handlers', 'register', 'deregister', 'upload_file', '_uploads'] \ No newline at end of file +__all__ = [ + "hooks", + "list_handlers", + "register", + "deregister", + "upload_file", + "_uploads", +] diff --git a/btrdbextras/eventproc/eventproc.py b/btrdbextras/eventproc/eventproc.py index f80b7d7..95b157b 100644 --- a/btrdbextras/eventproc/eventproc.py +++ b/btrdbextras/eventproc/eventproc.py @@ -17,26 +17,34 @@ import io import os -import warnings import uuid +import warnings from collections import namedtuple +import certifi import dill import grpc -import certifi from btrdb.utils.timez import ns_to_datetime -from btrdbextras.eventproc.protobuff import api_pb2 -from btrdbextras.eventproc.protobuff import api_pb2_grpc -__all__ = ['hooks', 'list_handlers', 'register', 'deregister', 'upload_file', '_uploads'] +from btrdbextras.eventproc.protobuff import api_pb2, api_pb2_grpc + +__all__ = [ + "hooks", + "list_handlers", + "register", + "deregister", + "upload_file", + "_uploads", +] _uploads = {} -PATH_PREFIX="/eventproc" +PATH_PREFIX = "/eventproc" ########################################################################## ## Helper Functions ########################################################################## + def connect(conn): parts = conn.endpoint.split(":", 2) endpoint = conn.endpoint + PATH_PREFIX @@ -67,7 +75,9 @@ def connect(conn): except Exception: if env_bundle != "": # The user has given us something but we can't use it, we need to make noise - raise Exception("BTRDB_CA_BUNDLE(%s) env is defined but could not read file" % ca_bundle) + raise Exception( + "BTRDB_CA_BUNDLE(%s) env is defined but could not read file" % ca_bundle + ) else: contents = None @@ -75,8 +85,8 @@ def connect(conn): endpoint, grpc.composite_channel_credentials( grpc.ssl_channel_credentials(contents), - grpc.access_token_call_credentials(apikey) - ) + grpc.access_token_call_credentials(apikey), + ), ) @@ -84,7 +94,11 @@ def connect(conn): ## Helper Classes ########################################################################## -HandlerBase = namedtuple("HandlerBase", "id name hook version notify_on_success notify_on_failure tags created_at created_by updated_at updated_by") +HandlerBase = namedtuple( + "HandlerBase", + "id name hook version notify_on_success notify_on_failure tags created_at created_by updated_at updated_by", +) + class Handler(HandlerBase): """ @@ -95,11 +109,20 @@ class Handler(HandlerBase): @classmethod def from_grpc(cls, h): return cls( - h.id, h.name, h.hook, h.version, h.notify_on_success, h.notify_on_failure, - h.tag, ns_to_datetime(h.created_at), h.created_by, - ns_to_datetime(h.updated_at), h.updated_by + h.id, + h.name, + h.hook, + h.version, + h.notify_on_success, + h.notify_on_failure, + h.tag, + ns_to_datetime(h.created_at), + h.created_by, + ns_to_datetime(h.updated_at), + h.updated_by, ) + class Service(object): """ Helper class to integrate with GRPC generated code. @@ -120,7 +143,17 @@ def ListHandlers(self, hook): for result in response.handlers: yield result - def Register(self, name, hook, func, apikey, notify_on_success, notify_on_failure, dependencies, tags): + def Register( + self, + name, + hook, + func, + apikey, + notify_on_success, + notify_on_failure, + dependencies, + tags, + ): # convert decorated function to bytes buff = io.BytesIO() dill.dump(func, buff) @@ -128,14 +161,14 @@ def Register(self, name, hook, func, apikey, notify_on_success, notify_on_failur params = api_pb2.RegisterRequest( registration=api_pb2.Registration( - name=name, - hook=hook, - blob=buff.read(), - api_key=apikey, - notify_on_success=notify_on_success, - notify_on_failure=notify_on_failure, - dependencies=dependencies, - tags=tags, + name=name, + hook=hook, + blob=buff.read(), + api_key=apikey, + notify_on_success=notify_on_success, + notify_on_failure=notify_on_failure, + dependencies=dependencies, + tags=tags, ) ) @@ -153,6 +186,7 @@ def Deregister(self, handler_id): ## Public Functions ########################################################################## + def hooks(conn): """ List registered hooks. @@ -165,6 +199,7 @@ def hooks(conn): s = Service(connect(conn)) return s.ListHooks() + def list_handlers(conn, hook=""): """ List registered handlers. An optional hook name is allowed to filter @@ -227,16 +262,25 @@ def register(conn, name, hook, notify_on_success, notify_on_failure, tags=None): # inner will actually receive the decorated func but we still have access # to the args & kwargs due to closure/scope. def inner(func): - # call grpc service to register event handler s = Service(connect(conn)) - _ = s.Register(name, hook, func, conn.apikey, notify_on_success, notify_on_failure, dependencies, tags) + _ = s.Register( + name, + hook, + func, + conn.apikey, + notify_on_success, + notify_on_failure, + dependencies, + tags, + ) # return original func back to user return func return inner + def upload_file(file, file_name): """ Uploads file to S3. Returns a link to download the file. @@ -256,12 +300,12 @@ def upload_file(file, file_name): TypeError: file_name must be a string. ValueError: file must be a path to a file, relative to the home directory. ValueError: file_name cannot be longer than 200 characters, is . - + Returns ---------- string: Download link to the object. None if upload was not attempted. """ - + # check the inputs if not isinstance(file, str): raise TypeError("file must be a string.") @@ -270,16 +314,20 @@ def upload_file(file, file_name): if not os.path.exists(file): raise ValueError("file must be a path to a file.") if len(file_name) > 200: - raise ValueError("file_name cannot be longer than 200 characters, is {0}.".format(len(file_name))) + raise ValueError( + "file_name cannot be longer than 200 characters, is {0}.".format( + len(file_name) + ) + ) # check the context if not os.getenv("EXECUTOR_CONTEXT") == "true": m = "upload_file is running in an execution context without the appropriate AWS credentials and will not upload to S3." warnings.warn(m) return None - + # queue the upload, to be completed by the executor when the handler completes code = str(uuid.uuid4().hex) _uploads[code] = [file, file_name] - - return "https://{0}/{1}".format(os.getenv("DOWNLOADS_ENDPOINT"), code) \ No newline at end of file + + return "https://{0}/{1}".format(os.getenv("DOWNLOADS_ENDPOINT"), code) diff --git a/btrdbextras/eventproc/protobuff/api_pb2.py b/btrdbextras/eventproc/protobuff/api_pb2.py index b08d400..bd69e75 100644 --- a/btrdbextras/eventproc/protobuff/api_pb2.py +++ b/btrdbextras/eventproc/protobuff/api_pb2.py @@ -6,651 +6,1006 @@ from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() - - DESCRIPTOR = _descriptor.FileDescriptor( - name='api.proto', - package='eventprocapi', - syntax='proto3', - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\tapi.proto\x12\x0c\x65ventprocapi\"#\n\x13ListHandlersRequest\x12\x0c\n\x04hook\x18\x01 \x01(\t\"?\n\x14ListHandlersResponse\x12\'\n\x08handlers\x18\x01 \x03(\x0b\x32\x15.eventprocapi.Handler\"\xe7\x01\n\x07Handler\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04hook\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\x05\x12\x10\n\x08\x63\x61llable\x18\x05 \x01(\t\x12\x0b\n\x03tag\x18\x06 \x03(\t\x12\x19\n\x11notify_on_success\x18\x07 \x01(\t\x12\x19\n\x11notify_on_failure\x18\x08 \x01(\t\x12\x12\n\ncreated_by\x18\t \x01(\t\x12\x12\n\ncreated_at\x18\n \x01(\x03\x12\x12\n\nupdated_by\x18\x0b \x01(\t\x12\x12\n\nupdated_at\x18\x0c \x01(\x03\"\x12\n\x10ListHooksRequest\"6\n\x11ListHooksResponse\x12!\n\x05hooks\x18\x01 \x03(\x0b\x32\x12.eventprocapi.Hook\"\x14\n\x04Hook\x12\x0c\n\x04name\x18\x01 \x01(\t\"\xb1\x01\n\x0cRegistration\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04hook\x18\x02 \x01(\t\x12\x0c\n\x04tags\x18\x03 \x03(\t\x12\x0c\n\x04\x62lob\x18\x04 \x01(\x0c\x12\x19\n\x11notify_on_success\x18\x05 \x01(\t\x12\x19\n\x11notify_on_failure\x18\x06 \x01(\t\x12\x14\n\x0c\x64\x65pendencies\x18\x07 \x01(\t\x12\x0c\n\x04user\x18\x08 \x01(\t\x12\x0f\n\x07\x61pi_key\x18\t \x01(\t\"C\n\x0fRegisterRequest\x12\x30\n\x0cregistration\x18\x01 \x01(\x0b\x32\x1a.eventprocapi.Registration\":\n\x10RegisterResponse\x12&\n\x07handler\x18\x01 \x01(\x0b\x32\x15.eventprocapi.Handler\"\x1f\n\x11\x44\x65registerRequest\x12\n\n\x02id\x18\x01 \x01(\x05\" \n\x12\x44\x65registerResponse\x12\n\n\x02id\x18\x01 \x01(\x05\x32\xe1\x02\n\x16\x45ventProcessingService\x12N\n\tListHooks\x12\x1e.eventprocapi.ListHooksRequest\x1a\x1f.eventprocapi.ListHooksResponse\"\x00\x12W\n\x0cListHandlers\x12!.eventprocapi.ListHandlersRequest\x1a\".eventprocapi.ListHandlersResponse\"\x00\x12K\n\x08Register\x12\x1d.eventprocapi.RegisterRequest\x1a\x1e.eventprocapi.RegisterResponse\"\x00\x12Q\n\nDeregister\x12\x1f.eventprocapi.DeregisterRequest\x1a .eventprocapi.DeregisterResponse\"\x00\x62\x06proto3' + name="api.proto", + package="eventprocapi", + syntax="proto3", + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\tapi.proto\x12\x0c\x65ventprocapi"#\n\x13ListHandlersRequest\x12\x0c\n\x04hook\x18\x01 \x01(\t"?\n\x14ListHandlersResponse\x12\'\n\x08handlers\x18\x01 \x03(\x0b\x32\x15.eventprocapi.Handler"\xe7\x01\n\x07Handler\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04hook\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\x05\x12\x10\n\x08\x63\x61llable\x18\x05 \x01(\t\x12\x0b\n\x03tag\x18\x06 \x03(\t\x12\x19\n\x11notify_on_success\x18\x07 \x01(\t\x12\x19\n\x11notify_on_failure\x18\x08 \x01(\t\x12\x12\n\ncreated_by\x18\t \x01(\t\x12\x12\n\ncreated_at\x18\n \x01(\x03\x12\x12\n\nupdated_by\x18\x0b \x01(\t\x12\x12\n\nupdated_at\x18\x0c \x01(\x03"\x12\n\x10ListHooksRequest"6\n\x11ListHooksResponse\x12!\n\x05hooks\x18\x01 \x03(\x0b\x32\x12.eventprocapi.Hook"\x14\n\x04Hook\x12\x0c\n\x04name\x18\x01 \x01(\t"\xb1\x01\n\x0cRegistration\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04hook\x18\x02 \x01(\t\x12\x0c\n\x04tags\x18\x03 \x03(\t\x12\x0c\n\x04\x62lob\x18\x04 \x01(\x0c\x12\x19\n\x11notify_on_success\x18\x05 \x01(\t\x12\x19\n\x11notify_on_failure\x18\x06 \x01(\t\x12\x14\n\x0c\x64\x65pendencies\x18\x07 \x01(\t\x12\x0c\n\x04user\x18\x08 \x01(\t\x12\x0f\n\x07\x61pi_key\x18\t \x01(\t"C\n\x0fRegisterRequest\x12\x30\n\x0cregistration\x18\x01 \x01(\x0b\x32\x1a.eventprocapi.Registration":\n\x10RegisterResponse\x12&\n\x07handler\x18\x01 \x01(\x0b\x32\x15.eventprocapi.Handler"\x1f\n\x11\x44\x65registerRequest\x12\n\n\x02id\x18\x01 \x01(\x05" \n\x12\x44\x65registerResponse\x12\n\n\x02id\x18\x01 \x01(\x05\x32\xe1\x02\n\x16\x45ventProcessingService\x12N\n\tListHooks\x12\x1e.eventprocapi.ListHooksRequest\x1a\x1f.eventprocapi.ListHooksResponse"\x00\x12W\n\x0cListHandlers\x12!.eventprocapi.ListHandlersRequest\x1a".eventprocapi.ListHandlersResponse"\x00\x12K\n\x08Register\x12\x1d.eventprocapi.RegisterRequest\x1a\x1e.eventprocapi.RegisterResponse"\x00\x12Q\n\nDeregister\x12\x1f.eventprocapi.DeregisterRequest\x1a .eventprocapi.DeregisterResponse"\x00\x62\x06proto3', ) - - _LISTHANDLERSREQUEST = _descriptor.Descriptor( - name='ListHandlersRequest', - full_name='eventprocapi.ListHandlersRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='hook', full_name='eventprocapi.ListHandlersRequest.hook', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=27, - serialized_end=62, + name="ListHandlersRequest", + full_name="eventprocapi.ListHandlersRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="hook", + full_name="eventprocapi.ListHandlersRequest.hook", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=27, + serialized_end=62, ) _LISTHANDLERSRESPONSE = _descriptor.Descriptor( - name='ListHandlersResponse', - full_name='eventprocapi.ListHandlersResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='handlers', full_name='eventprocapi.ListHandlersResponse.handlers', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=64, - serialized_end=127, + name="ListHandlersResponse", + full_name="eventprocapi.ListHandlersResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="handlers", + full_name="eventprocapi.ListHandlersResponse.handlers", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=64, + serialized_end=127, ) _HANDLER = _descriptor.Descriptor( - name='Handler', - full_name='eventprocapi.Handler', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='id', full_name='eventprocapi.Handler.id', index=0, - number=1, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='hook', full_name='eventprocapi.Handler.hook', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='name', full_name='eventprocapi.Handler.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='version', full_name='eventprocapi.Handler.version', index=3, - number=4, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='callable', full_name='eventprocapi.Handler.callable', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='tag', full_name='eventprocapi.Handler.tag', index=5, - number=6, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='notify_on_success', full_name='eventprocapi.Handler.notify_on_success', index=6, - number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='notify_on_failure', full_name='eventprocapi.Handler.notify_on_failure', index=7, - number=8, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='created_by', full_name='eventprocapi.Handler.created_by', index=8, - number=9, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='created_at', full_name='eventprocapi.Handler.created_at', index=9, - number=10, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='updated_by', full_name='eventprocapi.Handler.updated_by', index=10, - number=11, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='updated_at', full_name='eventprocapi.Handler.updated_at', index=11, - number=12, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=130, - serialized_end=361, + name="Handler", + full_name="eventprocapi.Handler", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="id", + full_name="eventprocapi.Handler.id", + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="hook", + full_name="eventprocapi.Handler.hook", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="eventprocapi.Handler.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="version", + full_name="eventprocapi.Handler.version", + index=3, + number=4, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="callable", + full_name="eventprocapi.Handler.callable", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="tag", + full_name="eventprocapi.Handler.tag", + index=5, + number=6, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="notify_on_success", + full_name="eventprocapi.Handler.notify_on_success", + index=6, + number=7, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="notify_on_failure", + full_name="eventprocapi.Handler.notify_on_failure", + index=7, + number=8, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="created_by", + full_name="eventprocapi.Handler.created_by", + index=8, + number=9, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="created_at", + full_name="eventprocapi.Handler.created_at", + index=9, + number=10, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="updated_by", + full_name="eventprocapi.Handler.updated_by", + index=10, + number=11, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="updated_at", + full_name="eventprocapi.Handler.updated_at", + index=11, + number=12, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=130, + serialized_end=361, ) _LISTHOOKSREQUEST = _descriptor.Descriptor( - name='ListHooksRequest', - full_name='eventprocapi.ListHooksRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=363, - serialized_end=381, + name="ListHooksRequest", + full_name="eventprocapi.ListHooksRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=363, + serialized_end=381, ) _LISTHOOKSRESPONSE = _descriptor.Descriptor( - name='ListHooksResponse', - full_name='eventprocapi.ListHooksResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='hooks', full_name='eventprocapi.ListHooksResponse.hooks', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=383, - serialized_end=437, + name="ListHooksResponse", + full_name="eventprocapi.ListHooksResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="hooks", + full_name="eventprocapi.ListHooksResponse.hooks", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=383, + serialized_end=437, ) _HOOK = _descriptor.Descriptor( - name='Hook', - full_name='eventprocapi.Hook', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='eventprocapi.Hook.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=439, - serialized_end=459, + name="Hook", + full_name="eventprocapi.Hook", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="eventprocapi.Hook.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=439, + serialized_end=459, ) _REGISTRATION = _descriptor.Descriptor( - name='Registration', - full_name='eventprocapi.Registration', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='eventprocapi.Registration.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='hook', full_name='eventprocapi.Registration.hook', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='tags', full_name='eventprocapi.Registration.tags', index=2, - number=3, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='blob', full_name='eventprocapi.Registration.blob', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='notify_on_success', full_name='eventprocapi.Registration.notify_on_success', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='notify_on_failure', full_name='eventprocapi.Registration.notify_on_failure', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='dependencies', full_name='eventprocapi.Registration.dependencies', index=6, - number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='user', full_name='eventprocapi.Registration.user', index=7, - number=8, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='api_key', full_name='eventprocapi.Registration.api_key', index=8, - number=9, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=462, - serialized_end=639, + name="Registration", + full_name="eventprocapi.Registration", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="eventprocapi.Registration.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="hook", + full_name="eventprocapi.Registration.hook", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="tags", + full_name="eventprocapi.Registration.tags", + index=2, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="blob", + full_name="eventprocapi.Registration.blob", + index=3, + number=4, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="notify_on_success", + full_name="eventprocapi.Registration.notify_on_success", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="notify_on_failure", + full_name="eventprocapi.Registration.notify_on_failure", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="dependencies", + full_name="eventprocapi.Registration.dependencies", + index=6, + number=7, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="user", + full_name="eventprocapi.Registration.user", + index=7, + number=8, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="api_key", + full_name="eventprocapi.Registration.api_key", + index=8, + number=9, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=462, + serialized_end=639, ) _REGISTERREQUEST = _descriptor.Descriptor( - name='RegisterRequest', - full_name='eventprocapi.RegisterRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='registration', full_name='eventprocapi.RegisterRequest.registration', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=641, - serialized_end=708, + name="RegisterRequest", + full_name="eventprocapi.RegisterRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="registration", + full_name="eventprocapi.RegisterRequest.registration", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=641, + serialized_end=708, ) _REGISTERRESPONSE = _descriptor.Descriptor( - name='RegisterResponse', - full_name='eventprocapi.RegisterResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='handler', full_name='eventprocapi.RegisterResponse.handler', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=710, - serialized_end=768, + name="RegisterResponse", + full_name="eventprocapi.RegisterResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="handler", + full_name="eventprocapi.RegisterResponse.handler", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=710, + serialized_end=768, ) _DEREGISTERREQUEST = _descriptor.Descriptor( - name='DeregisterRequest', - full_name='eventprocapi.DeregisterRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='id', full_name='eventprocapi.DeregisterRequest.id', index=0, - number=1, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=770, - serialized_end=801, + name="DeregisterRequest", + full_name="eventprocapi.DeregisterRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="id", + full_name="eventprocapi.DeregisterRequest.id", + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=770, + serialized_end=801, ) _DEREGISTERRESPONSE = _descriptor.Descriptor( - name='DeregisterResponse', - full_name='eventprocapi.DeregisterResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='id', full_name='eventprocapi.DeregisterResponse.id', index=0, - number=1, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=803, - serialized_end=835, + name="DeregisterResponse", + full_name="eventprocapi.DeregisterResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="id", + full_name="eventprocapi.DeregisterResponse.id", + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=803, + serialized_end=835, ) -_LISTHANDLERSRESPONSE.fields_by_name['handlers'].message_type = _HANDLER -_LISTHOOKSRESPONSE.fields_by_name['hooks'].message_type = _HOOK -_REGISTERREQUEST.fields_by_name['registration'].message_type = _REGISTRATION -_REGISTERRESPONSE.fields_by_name['handler'].message_type = _HANDLER -DESCRIPTOR.message_types_by_name['ListHandlersRequest'] = _LISTHANDLERSREQUEST -DESCRIPTOR.message_types_by_name['ListHandlersResponse'] = _LISTHANDLERSRESPONSE -DESCRIPTOR.message_types_by_name['Handler'] = _HANDLER -DESCRIPTOR.message_types_by_name['ListHooksRequest'] = _LISTHOOKSREQUEST -DESCRIPTOR.message_types_by_name['ListHooksResponse'] = _LISTHOOKSRESPONSE -DESCRIPTOR.message_types_by_name['Hook'] = _HOOK -DESCRIPTOR.message_types_by_name['Registration'] = _REGISTRATION -DESCRIPTOR.message_types_by_name['RegisterRequest'] = _REGISTERREQUEST -DESCRIPTOR.message_types_by_name['RegisterResponse'] = _REGISTERRESPONSE -DESCRIPTOR.message_types_by_name['DeregisterRequest'] = _DEREGISTERREQUEST -DESCRIPTOR.message_types_by_name['DeregisterResponse'] = _DEREGISTERRESPONSE +_LISTHANDLERSRESPONSE.fields_by_name["handlers"].message_type = _HANDLER +_LISTHOOKSRESPONSE.fields_by_name["hooks"].message_type = _HOOK +_REGISTERREQUEST.fields_by_name["registration"].message_type = _REGISTRATION +_REGISTERRESPONSE.fields_by_name["handler"].message_type = _HANDLER +DESCRIPTOR.message_types_by_name["ListHandlersRequest"] = _LISTHANDLERSREQUEST +DESCRIPTOR.message_types_by_name["ListHandlersResponse"] = _LISTHANDLERSRESPONSE +DESCRIPTOR.message_types_by_name["Handler"] = _HANDLER +DESCRIPTOR.message_types_by_name["ListHooksRequest"] = _LISTHOOKSREQUEST +DESCRIPTOR.message_types_by_name["ListHooksResponse"] = _LISTHOOKSRESPONSE +DESCRIPTOR.message_types_by_name["Hook"] = _HOOK +DESCRIPTOR.message_types_by_name["Registration"] = _REGISTRATION +DESCRIPTOR.message_types_by_name["RegisterRequest"] = _REGISTERREQUEST +DESCRIPTOR.message_types_by_name["RegisterResponse"] = _REGISTERRESPONSE +DESCRIPTOR.message_types_by_name["DeregisterRequest"] = _DEREGISTERREQUEST +DESCRIPTOR.message_types_by_name["DeregisterResponse"] = _DEREGISTERRESPONSE _sym_db.RegisterFileDescriptor(DESCRIPTOR) -ListHandlersRequest = _reflection.GeneratedProtocolMessageType('ListHandlersRequest', (_message.Message,), { - 'DESCRIPTOR' : _LISTHANDLERSREQUEST, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.ListHandlersRequest) - }) +ListHandlersRequest = _reflection.GeneratedProtocolMessageType( + "ListHandlersRequest", + (_message.Message,), + { + "DESCRIPTOR": _LISTHANDLERSREQUEST, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.ListHandlersRequest) + }, +) _sym_db.RegisterMessage(ListHandlersRequest) -ListHandlersResponse = _reflection.GeneratedProtocolMessageType('ListHandlersResponse', (_message.Message,), { - 'DESCRIPTOR' : _LISTHANDLERSRESPONSE, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.ListHandlersResponse) - }) +ListHandlersResponse = _reflection.GeneratedProtocolMessageType( + "ListHandlersResponse", + (_message.Message,), + { + "DESCRIPTOR": _LISTHANDLERSRESPONSE, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.ListHandlersResponse) + }, +) _sym_db.RegisterMessage(ListHandlersResponse) -Handler = _reflection.GeneratedProtocolMessageType('Handler', (_message.Message,), { - 'DESCRIPTOR' : _HANDLER, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.Handler) - }) +Handler = _reflection.GeneratedProtocolMessageType( + "Handler", + (_message.Message,), + { + "DESCRIPTOR": _HANDLER, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.Handler) + }, +) _sym_db.RegisterMessage(Handler) -ListHooksRequest = _reflection.GeneratedProtocolMessageType('ListHooksRequest', (_message.Message,), { - 'DESCRIPTOR' : _LISTHOOKSREQUEST, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.ListHooksRequest) - }) +ListHooksRequest = _reflection.GeneratedProtocolMessageType( + "ListHooksRequest", + (_message.Message,), + { + "DESCRIPTOR": _LISTHOOKSREQUEST, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.ListHooksRequest) + }, +) _sym_db.RegisterMessage(ListHooksRequest) -ListHooksResponse = _reflection.GeneratedProtocolMessageType('ListHooksResponse', (_message.Message,), { - 'DESCRIPTOR' : _LISTHOOKSRESPONSE, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.ListHooksResponse) - }) +ListHooksResponse = _reflection.GeneratedProtocolMessageType( + "ListHooksResponse", + (_message.Message,), + { + "DESCRIPTOR": _LISTHOOKSRESPONSE, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.ListHooksResponse) + }, +) _sym_db.RegisterMessage(ListHooksResponse) -Hook = _reflection.GeneratedProtocolMessageType('Hook', (_message.Message,), { - 'DESCRIPTOR' : _HOOK, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.Hook) - }) +Hook = _reflection.GeneratedProtocolMessageType( + "Hook", + (_message.Message,), + { + "DESCRIPTOR": _HOOK, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.Hook) + }, +) _sym_db.RegisterMessage(Hook) -Registration = _reflection.GeneratedProtocolMessageType('Registration', (_message.Message,), { - 'DESCRIPTOR' : _REGISTRATION, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.Registration) - }) +Registration = _reflection.GeneratedProtocolMessageType( + "Registration", + (_message.Message,), + { + "DESCRIPTOR": _REGISTRATION, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.Registration) + }, +) _sym_db.RegisterMessage(Registration) -RegisterRequest = _reflection.GeneratedProtocolMessageType('RegisterRequest', (_message.Message,), { - 'DESCRIPTOR' : _REGISTERREQUEST, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.RegisterRequest) - }) +RegisterRequest = _reflection.GeneratedProtocolMessageType( + "RegisterRequest", + (_message.Message,), + { + "DESCRIPTOR": _REGISTERREQUEST, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.RegisterRequest) + }, +) _sym_db.RegisterMessage(RegisterRequest) -RegisterResponse = _reflection.GeneratedProtocolMessageType('RegisterResponse', (_message.Message,), { - 'DESCRIPTOR' : _REGISTERRESPONSE, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.RegisterResponse) - }) +RegisterResponse = _reflection.GeneratedProtocolMessageType( + "RegisterResponse", + (_message.Message,), + { + "DESCRIPTOR": _REGISTERRESPONSE, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.RegisterResponse) + }, +) _sym_db.RegisterMessage(RegisterResponse) -DeregisterRequest = _reflection.GeneratedProtocolMessageType('DeregisterRequest', (_message.Message,), { - 'DESCRIPTOR' : _DEREGISTERREQUEST, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.DeregisterRequest) - }) +DeregisterRequest = _reflection.GeneratedProtocolMessageType( + "DeregisterRequest", + (_message.Message,), + { + "DESCRIPTOR": _DEREGISTERREQUEST, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.DeregisterRequest) + }, +) _sym_db.RegisterMessage(DeregisterRequest) -DeregisterResponse = _reflection.GeneratedProtocolMessageType('DeregisterResponse', (_message.Message,), { - 'DESCRIPTOR' : _DEREGISTERRESPONSE, - '__module__' : 'api_pb2' - # @@protoc_insertion_point(class_scope:eventprocapi.DeregisterResponse) - }) +DeregisterResponse = _reflection.GeneratedProtocolMessageType( + "DeregisterResponse", + (_message.Message,), + { + "DESCRIPTOR": _DEREGISTERRESPONSE, + "__module__": "api_pb2" + # @@protoc_insertion_point(class_scope:eventprocapi.DeregisterResponse) + }, +) _sym_db.RegisterMessage(DeregisterResponse) - _EVENTPROCESSINGSERVICE = _descriptor.ServiceDescriptor( - name='EventProcessingService', - full_name='eventprocapi.EventProcessingService', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=838, - serialized_end=1191, - methods=[ - _descriptor.MethodDescriptor( - name='ListHooks', - full_name='eventprocapi.EventProcessingService.ListHooks', + name="EventProcessingService", + full_name="eventprocapi.EventProcessingService", + file=DESCRIPTOR, index=0, - containing_service=None, - input_type=_LISTHOOKSREQUEST, - output_type=_LISTHOOKSRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='ListHandlers', - full_name='eventprocapi.EventProcessingService.ListHandlers', - index=1, - containing_service=None, - input_type=_LISTHANDLERSREQUEST, - output_type=_LISTHANDLERSRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='Register', - full_name='eventprocapi.EventProcessingService.Register', - index=2, - containing_service=None, - input_type=_REGISTERREQUEST, - output_type=_REGISTERRESPONSE, serialized_options=None, create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='Deregister', - full_name='eventprocapi.EventProcessingService.Deregister', - index=3, - containing_service=None, - input_type=_DEREGISTERREQUEST, - output_type=_DEREGISTERRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), -]) + serialized_start=838, + serialized_end=1191, + methods=[ + _descriptor.MethodDescriptor( + name="ListHooks", + full_name="eventprocapi.EventProcessingService.ListHooks", + index=0, + containing_service=None, + input_type=_LISTHOOKSREQUEST, + output_type=_LISTHOOKSRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="ListHandlers", + full_name="eventprocapi.EventProcessingService.ListHandlers", + index=1, + containing_service=None, + input_type=_LISTHANDLERSREQUEST, + output_type=_LISTHANDLERSRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="Register", + full_name="eventprocapi.EventProcessingService.Register", + index=2, + containing_service=None, + input_type=_REGISTERREQUEST, + output_type=_REGISTERRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name="Deregister", + full_name="eventprocapi.EventProcessingService.Deregister", + index=3, + containing_service=None, + input_type=_DEREGISTERREQUEST, + output_type=_DEREGISTERRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + ], +) _sym_db.RegisterServiceDescriptor(_EVENTPROCESSINGSERVICE) -DESCRIPTOR.services_by_name['EventProcessingService'] = _EVENTPROCESSINGSERVICE +DESCRIPTOR.services_by_name["EventProcessingService"] = _EVENTPROCESSINGSERVICE # @@protoc_insertion_point(module_scope) diff --git a/btrdbextras/eventproc/protobuff/api_pb2_grpc.py b/btrdbextras/eventproc/protobuff/api_pb2_grpc.py index ec3abe4..ac02e3d 100644 --- a/btrdbextras/eventproc/protobuff/api_pb2_grpc.py +++ b/btrdbextras/eventproc/protobuff/api_pb2_grpc.py @@ -4,6 +4,7 @@ import btrdbextras.eventproc.protobuff.api_pb2 as api__pb2 + class EventProcessingServiceStub(object): """Missing associated documentation comment in .proto file.""" @@ -14,25 +15,25 @@ def __init__(self, channel): channel: A grpc.Channel. """ self.ListHooks = channel.unary_unary( - '/eventprocapi.EventProcessingService/ListHooks', - request_serializer=api__pb2.ListHooksRequest.SerializeToString, - response_deserializer=api__pb2.ListHooksResponse.FromString, - ) + "/eventprocapi.EventProcessingService/ListHooks", + request_serializer=api__pb2.ListHooksRequest.SerializeToString, + response_deserializer=api__pb2.ListHooksResponse.FromString, + ) self.ListHandlers = channel.unary_unary( - '/eventprocapi.EventProcessingService/ListHandlers', - request_serializer=api__pb2.ListHandlersRequest.SerializeToString, - response_deserializer=api__pb2.ListHandlersResponse.FromString, - ) + "/eventprocapi.EventProcessingService/ListHandlers", + request_serializer=api__pb2.ListHandlersRequest.SerializeToString, + response_deserializer=api__pb2.ListHandlersResponse.FromString, + ) self.Register = channel.unary_unary( - '/eventprocapi.EventProcessingService/Register', - request_serializer=api__pb2.RegisterRequest.SerializeToString, - response_deserializer=api__pb2.RegisterResponse.FromString, - ) + "/eventprocapi.EventProcessingService/Register", + request_serializer=api__pb2.RegisterRequest.SerializeToString, + response_deserializer=api__pb2.RegisterResponse.FromString, + ) self.Deregister = channel.unary_unary( - '/eventprocapi.EventProcessingService/Deregister', - request_serializer=api__pb2.DeregisterRequest.SerializeToString, - response_deserializer=api__pb2.DeregisterResponse.FromString, - ) + "/eventprocapi.EventProcessingService/Deregister", + request_serializer=api__pb2.DeregisterRequest.SerializeToString, + response_deserializer=api__pb2.DeregisterResponse.FromString, + ) class EventProcessingServiceServicer(object): @@ -41,124 +42,173 @@ class EventProcessingServiceServicer(object): def ListHooks(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def ListHandlers(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def Register(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def Deregister(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') + context.set_details("Method not implemented!") + raise NotImplementedError("Method not implemented!") def add_EventProcessingServiceServicer_to_server(servicer, server): rpc_method_handlers = { - 'ListHooks': grpc.unary_unary_rpc_method_handler( - servicer.ListHooks, - request_deserializer=api__pb2.ListHooksRequest.FromString, - response_serializer=api__pb2.ListHooksResponse.SerializeToString, - ), - 'ListHandlers': grpc.unary_unary_rpc_method_handler( - servicer.ListHandlers, - request_deserializer=api__pb2.ListHandlersRequest.FromString, - response_serializer=api__pb2.ListHandlersResponse.SerializeToString, - ), - 'Register': grpc.unary_unary_rpc_method_handler( - servicer.Register, - request_deserializer=api__pb2.RegisterRequest.FromString, - response_serializer=api__pb2.RegisterResponse.SerializeToString, - ), - 'Deregister': grpc.unary_unary_rpc_method_handler( - servicer.Deregister, - request_deserializer=api__pb2.DeregisterRequest.FromString, - response_serializer=api__pb2.DeregisterResponse.SerializeToString, - ), + "ListHooks": grpc.unary_unary_rpc_method_handler( + servicer.ListHooks, + request_deserializer=api__pb2.ListHooksRequest.FromString, + response_serializer=api__pb2.ListHooksResponse.SerializeToString, + ), + "ListHandlers": grpc.unary_unary_rpc_method_handler( + servicer.ListHandlers, + request_deserializer=api__pb2.ListHandlersRequest.FromString, + response_serializer=api__pb2.ListHandlersResponse.SerializeToString, + ), + "Register": grpc.unary_unary_rpc_method_handler( + servicer.Register, + request_deserializer=api__pb2.RegisterRequest.FromString, + response_serializer=api__pb2.RegisterResponse.SerializeToString, + ), + "Deregister": grpc.unary_unary_rpc_method_handler( + servicer.Deregister, + request_deserializer=api__pb2.DeregisterRequest.FromString, + response_serializer=api__pb2.DeregisterResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'eventprocapi.EventProcessingService', rpc_method_handlers) + "eventprocapi.EventProcessingService", rpc_method_handlers + ) server.add_generic_rpc_handlers((generic_handler,)) - # This class is part of an EXPERIMENTAL API. +# This class is part of an EXPERIMENTAL API. class EventProcessingService(object): """Missing associated documentation comment in .proto file.""" @staticmethod - def ListHooks(request, + def ListHooks( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/eventprocapi.EventProcessingService/ListHooks', + "/eventprocapi.EventProcessingService/ListHooks", api__pb2.ListHooksRequest.SerializeToString, api__pb2.ListHooksResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def ListHandlers(request, + def ListHandlers( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/eventprocapi.EventProcessingService/ListHandlers', + "/eventprocapi.EventProcessingService/ListHandlers", api__pb2.ListHandlersRequest.SerializeToString, api__pb2.ListHandlersResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def Register(request, + def Register( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/eventprocapi.EventProcessingService/Register', + "/eventprocapi.EventProcessingService/Register", api__pb2.RegisterRequest.SerializeToString, api__pb2.RegisterResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) @staticmethod - def Deregister(request, + def Deregister( + request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None, + ): + return grpc.experimental.unary_unary( + request, target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/eventprocapi.EventProcessingService/Deregister', + "/eventprocapi.EventProcessingService/Deregister", api__pb2.DeregisterRequest.SerializeToString, api__pb2.DeregisterResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + ) diff --git a/docs/source/conf.py b/docs/source/conf.py index 3e27d73..d44492a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,15 +16,16 @@ import os import sys -sys.path.insert(0, os.path.abspath('../..')) + +sys.path.insert(0, os.path.abspath("../..")) import sphinx_glpi_theme # -- Project information ----------------------------------------------------- -project = 'btrdbextras' -copyright = '2020, PingThings, Inc.' -author = 'PingThings, Inc.' +project = "btrdbextras" +copyright = "2020, PingThings, Inc." +author = "PingThings, Inc." # -- General configuration --------------------------------------------------- @@ -33,19 +34,19 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.githubpages', - 'sphinx.ext.intersphinx', + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx.ext.githubpages", + "sphinx.ext.intersphinx", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- @@ -57,4 +58,4 @@ html_theme = "glpi" -html_theme_path = sphinx_glpi_theme.get_html_themes_path() \ No newline at end of file +html_theme_path = sphinx_glpi_theme.get_html_themes_path() diff --git a/docs/source/eventproc.rst b/docs/source/eventproc.rst index cd7c4d5..d0a73b1 100644 --- a/docs/source/eventproc.rst +++ b/docs/source/eventproc.rst @@ -313,4 +313,4 @@ Assuming you chose to use variadic arguments (i.e., `**kwargs`) in your event ha 'File': 'comtrade_samples.zip', 'RequestID': '0bbcacdb-e7aa-4e01-af88-9ba865ea32bd', 'SubmittedAt': '2020-10-29T21:58:15.09246084Z' - } \ No newline at end of file + } diff --git a/docs/source/installing.rst b/docs/source/installing.rst index 50dfba4..b6c4948 100644 --- a/docs/source/installing.rst +++ b/docs/source/installing.rst @@ -17,4 +17,3 @@ To upgrade using pip: .. code-block:: bash $ pip install -U btrdbextras - diff --git a/release.sh b/release.sh index ba08e6e..d53028c 100755 --- a/release.sh +++ b/release.sh @@ -45,4 +45,4 @@ git tag v$1.$2.$3 git push origin v$1.$2.$3 sleep 10 -git push \ No newline at end of file +git push diff --git a/requirements.txt b/requirements.txt index a613877..1c1920a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,4 @@ tabulate==0.8.9 certifi # Readthedocs -sphinx_glpi_theme \ No newline at end of file +sphinx_glpi_theme diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..00eb245 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,58 @@ +[metadata] +description-file = README.md +license_file = LICENSE.txt + +[test] +local_freetype = True +tests = True + +[aliases] +test=pytest + +[flake8] +max-line-length = 88 +exclude = .git build dist +statistics = True +count = True +select = + E9 + F63 + F7 + F82 +extend-ignore = + E111 + E114 + E121 + E122 + E123 + E124 + E128 + E201 + E202 + E203 + E221 + E222 + E225 + E226 + E231 + E241 + E251 + E266 + E271 + E302 + E303 + E402 + E501 + E502 + E701 + E731 + F401 + W292 + W293 + W391 + W605 + W503 + W504 + +[coverage:run] +omit = */tests/* diff --git a/setup.py b/setup.py index d5c5592..49bdf75 100644 --- a/setup.py +++ b/setup.py @@ -16,11 +16,10 @@ ## Imports ########################################################################## -import os import codecs +import os -from setuptools import setup -from setuptools import find_packages +from setuptools import find_packages, setup from btrdbextras import __version__ @@ -29,59 +28,63 @@ ########################################################################## ## Basic information -NAME = "btrdbextras" -DESCRIPTION = "Enhancements additional features to interact with the Berkeley Tree Database" -AUTHOR = "Allen Leis" -EMAIL = "allen@pingthings.io" -MAINTAINER = "Allen Leis" -LICENSE = "BSD-3-Clause" -REPOSITORY = "https://github.com/PingThingsIO/btrdbextras" -PACKAGE = "btrdb" -URL = "https://btrdbextras.readthedocs.io/en/latest/" -DOCS_URL = "https://btrdbextras.readthedocs.io/en/latest/" +NAME = "btrdbextras" +DESCRIPTION = ( + "Enhancements additional features to interact with the Berkeley Tree Database" +) +AUTHOR = "Allen Leis" +EMAIL = "allen@pingthings.io" +MAINTAINER = "Allen Leis" +LICENSE = "BSD-3-Clause" +REPOSITORY = "https://github.com/PingThingsIO/btrdbextras" +PACKAGE = "btrdb" +URL = "https://btrdbextras.readthedocs.io/en/latest/" +DOCS_URL = "https://btrdbextras.readthedocs.io/en/latest/" ## Define the keywords -KEYWORDS = ('btrdb', 'timeseries', 'database') +KEYWORDS = ("btrdb", "timeseries", "database") ## Define the classifiers ## See https://pypi.python.org/pypi?%3Aaction=list_classifiers -CLASSIFIERS = ( - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: BSD License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Topic :: Database', - 'Topic :: Software Development :: Libraries :: Python Modules', +CLASSIFIERS = ( + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Topic :: Database", + "Topic :: Software Development :: Libraries :: Python Modules", ) ## Important Paths -PROJECT = os.path.abspath(os.path.dirname(__file__)) +PROJECT = os.path.abspath(os.path.dirname(__file__)) REQUIRE_PATH = "requirements.txt" VERSION_PATH = os.path.join(PACKAGE, "version.py") PKG_DESCRIBE = "DESCRIPTION.md" ## Directories to ignore in find_packages -EXCLUDES = ( - "tests", "docs", +EXCLUDES = ( + "tests", + "docs", ) ########################################################################## ## Helper Functions ########################################################################## + def read(*parts): """ Assume UTF-8 encoding and return the contents of the file located at the absolute path from the REPOSITORY joined with *parts. """ - with codecs.open(os.path.join(PROJECT, *parts), 'rb', 'utf-8') as f: + with codecs.open(os.path.join(PROJECT, *parts), "rb", "utf-8") as f: return f.read() @@ -92,7 +95,7 @@ def get_requires(path=REQUIRE_PATH): """ for line in read(path).splitlines(): line = line.strip() - if line and not line.startswith('#'): + if line and not line.startswith("#"): yield line @@ -144,8 +147,8 @@ def get_description_type(path=PKG_DESCRIBE): }, "install_requires": list(get_requires()), "python_requires": ">=3.6, <4", - "setup_requires":["pytest-runner"], - "tests_require":["pytest"], + "setup_requires": ["pytest-runner"], + "tests_require": ["pytest"], } @@ -153,5 +156,5 @@ def get_description_type(path=PKG_DESCRIBE): ## Run setup script ########################################################################## -if __name__ == '__main__': +if __name__ == "__main__": setup(**config) diff --git a/tests/requirements.txt b/tests/requirements.txt index 60b339e..94366ed 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,3 @@ pytest==6.1.1 pytest-cov==2.10.1 -pytest-flakes==4.0.2 \ No newline at end of file +pytest-flakes==4.0.2 diff --git a/tests/test_base.py b/tests/test_base.py index 81ef9b6..4f76033 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -16,24 +16,25 @@ ########################################################################## import re + import pytest -from btrdbextras import __version__, Connection +from btrdbextras import Connection, __version__ ########################################################################## ## Initialization Tests ########################################################################## -class TestPackage(object): +class TestPackage(object): def test_version(self): """ Assert that the test version smells valid. """ assert bool(re.match(r"^v\d+\.\d+\.\d+$", __version__)) -class TestConnection(object): +class TestConnection(object): def test_properties(self): """ Connection contains apikey and endpoint From 36d12ea572e8fa9779bfcb16f25e72bc71fb89ff Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:49:17 -0800 Subject: [PATCH 02/10] update actions v2->v3 --- .github/workflows/release.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 09c37a5..8951694 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -18,9 +18,9 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} ${{ matrix.os }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -39,7 +39,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Create Release id: create_release uses: actions/create-release@v1 @@ -59,9 +59,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: '3.8' - name: Install dependencies From 874b95a70a79498b06f02acb3cd974cc1233770c Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:17:59 -0800 Subject: [PATCH 03/10] add pyproject.toml --- .gitignore | 14 +++++++++---- pyproject.toml | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore index d5ef9f4..4629a15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -# Local development -local-setup.sh -driver.py -ignore.py # OS trash .DS_Store @@ -122,3 +118,13 @@ dmypy.json # Pyre type checker .pyre/ + +# arrow parquet files +*.parquet + +.idea +.idea/misc.xml +.idea/vcs.xml +.idea/inspectionProfiles/profiles_settings.xml +.idea/inspectionProfiles/Project_Default.xml +/.idea/ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b34b2df --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,54 @@ +[project] +name = "btrdbextras" +version = "5.31.0" +description = "Enhancements additional features to interact with the Berkeley Tree Database" +authors = [ + {name="PingThingsIO", email="support@pingthings.io"}, +] +dependencies = [ + "btrdb>=5.11.7", + "certifi", + "dill==0.3.2", + "grpcio-tools>=1.16.1", + "grpcio>=1.16.1", + "sphinx_glpi_theme", + "tabulate==0.8.9", +] +requires-python = ">=3.6, <4" +readme = "README.md" +license = {file="LICENSE.txt"} +keywords = ["btrdb", "timeseries", "database"] + +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python", + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + "Topic :: Database", + "Topic :: Software Development :: Libraries :: Python Modules", +] + +[project.urls] +Homepage = "https://btrdbextras.readthedocs.io/en/latest/" +Downloads = "https://github.com/PingThingsIO/btrdbextras/tarball/v5.31.0" +Documentation = "https://btrdbextras.readthedocs.io/en/latest/" +Download = "https://github.com/PingThingsIO/btrdbextras/tarball/v5.31.0" +Source = "https://github.com/PingThingsIO/btrdbextras" +Tracker = "https://github.com/PingThingsIO/btrdbextras/issues" +[build-system] +requires = ["setuptools>=61"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.exclude-package-data] +drop = [ + "tests", + "docs" +] From acf5ec1094bbb30d891fa295ec5fbf7d24a7c1fb Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:24:10 -0800 Subject: [PATCH 04/10] update test requirements.txt --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 94366ed..4a08de2 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,3 @@ -pytest==6.1.1 +pytest==6.2.5 pytest-cov==2.10.1 pytest-flakes==4.0.2 From 325395018da906c089d8f3d1319bbe8d8ca223e2 Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:30:30 -0800 Subject: [PATCH 05/10] update pre-commit hooks --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c62cb0d..69de93a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,18 +1,18 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace exclude: setup.cfg - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.11.0 hooks: - id: black-jupyter args: [--line-length=88] - repo: https://github.com/pycqa/isort - rev: 5.11.5 + rev: 5.12.0 hooks: - id: isort name: isort (python) @@ -22,7 +22,7 @@ repos: hooks: # Enforce that python3.6+ type annotations are used instead of type comments - id: python-use-type-annotations - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 # args: [] From d92055f00f0f902f244950d9565d02446e6bc8b0 Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:35:30 -0800 Subject: [PATCH 06/10] update Makefile --- Makefile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e80d39d..01a5a59 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ SPHINXBUILDDIR = docs/build SPHINXSOURCEDIR = docs/source # Export targets not associated with files -.PHONY: test grpc +.PHONY: test coverage pip clean publish uml build deploy install # Clean build files clean: @@ -31,7 +31,12 @@ clean: -rm -rf docs/build -rm -rf platform-builds meta.yaml -# Generate new grpc code + +# Publish to gh-pages +publish: + git subtree push --prefix=deploy origin gh-pages + +# Autogenerate GRPC/PB files grpc: @echo Generating files: python -m grpc_tools.protoc -I btrdbextras/eventproc/protobuff --python_out=btrdbextras/eventproc/protobuff --grpc_python_out=btrdbextras/eventproc/protobuff btrdbextras/eventproc/protobuff/api.proto @@ -54,9 +59,11 @@ install: # Deploy to PyPI deploy: - # python setup.py register + python setup.py register twine upload dist/* --verbose # Build html version of docs html: $(SPHINXBUILD) -b html $(SPHINXOPTS) $(SPHINXSOURCEDIR) $(SPHINXBUILDDIR) + @echo + @echo "Build finished. The HTML pages are in $(SPHINXBUILDDIR)/html." From 62fe4a45cfaff5102639ccc69fa3da944af9dd4b Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:38:46 -0800 Subject: [PATCH 07/10] update docs/ --- docs/make.bat | 35 ----------------------------------- docs/requirements.txt | 7 +++++-- 2 files changed, 5 insertions(+), 37 deletions(-) delete mode 100644 docs/make.bat diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 6247f7e..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/requirements.txt b/docs/requirements.txt index d535bde..49e71d8 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,5 @@ -sphinx -sphinx_glpi_theme +alabaster>=0.7.12 +Sphinx>=1.7 +sphinx-rtd-theme +numpydoc +pydata-sphinx-theme From ae22e5379b15125fd23d7a3cc3d2cdaf1e096e2a Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:00:28 -0800 Subject: [PATCH 08/10] update __version__ and some of docs/sourc/conf.py --- btrdbextras/__init__.py | 2 +- .../IEEE_13_-_Create_Streams_Add_Data.ipynb | 5042 +++++++++++++++++ .../Intro_to_Simulation_with_OpenDSS.ipynb | 405 ++ docs/source/conf.py | 117 +- 4 files changed, 5556 insertions(+), 10 deletions(-) create mode 100644 btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb create mode 100644 btrdbextras/opendss_ingest/Intro_to_Simulation_with_OpenDSS.ipynb diff --git a/btrdbextras/__init__.py b/btrdbextras/__init__.py index 5e701f5..6d18cfe 100644 --- a/btrdbextras/__init__.py +++ b/btrdbextras/__init__.py @@ -1,5 +1,5 @@ from .conn import Connection -__version__ = "v5.11.9" +__version__ = "v5.31.0" __all__ = ["__version__", "Connection"] diff --git a/btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb b/btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb new file mode 100644 index 0000000..f0ec190 --- /dev/null +++ b/btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb @@ -0,0 +1,5042 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 146, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import opendssdirect as dss\n", + "import matplotlib.pyplot as plt\n", + "from tqdm.notebook import tqdm_notebook, tqdm\n", + "import btrdb as db\n", + "import uuid\n", + "from btrdb.utils.timez import datetime_to_ns\n", + "import simulation_utils as sims\n", + "from datetime import datetime, timedelta\n", + "\n", + "%matplotlib inline\n", + "\n", + "import importlib\n", + "\n", + "importlib.reload(sims);" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": {}, + "outputs": [], + "source": [ + "# Connect to the database\n", + "conn = db.connect(profile=\"collab\")" + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "metadata": {}, + "outputs": [], + "source": [ + "model_loc = \"./Models/13Bus/IEEE13Nodeckt.dss\"\n", + "dss.run_command(\"Redirect \" + model_loc);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create output streams\n", + "The following cells create the output streams or retrieve them if they have already been created. " + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": {}, + "outputs": [], + "source": [ + "prefix = \"simulated/ieee13\"\n", + "collections, names, tags, annotations = sims.get_stream_info(base_col=prefix)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nstreams = len(collections)\n", + "print(\"Creating\", nstreams, \"streams\")\n", + "for i in range(nstreams):\n", + " print(collections[i] + \"/\" + names[i])" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 234 streams under simulated/ieee13\n", + "Found 234 streams. Created 0 streams.\n" + ] + } + ], + "source": [ + "streams_dict = sims.create_streams(prefix, collections, names, tags, annotations, conn)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate simulated measurements\n", + "The following cell generates data that will be converted into streams. \n", + "For convenience, we back-calculate the number of samples from a user specified sample rate (`fs`) and simulation duration (`start_time` to `end_time`). However, keep in mind that the simulation has no inherent sense of time - we are abitrarily assigning timestamps to each simulation result. " + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We will generate 1800 samples.\n" + ] + } + ], + "source": [ + "# The number of samples to generate\n", + "start_time = datetime(2022, 1, 1, 0, 0, 0)\n", + "end_time = datetime(2022, 1, 1, 0, 1, 0)\n", + "fs = 30 # Hz\n", + "T = int(((end_time - start_time).total_seconds()) * fs)\n", + "print(\"We will generate\", T, \"samples.\")\n", + "\n", + "# Generate the nanosecond timestamps for the data\n", + "start_ns = datetime_to_ns(start_time)\n", + "end_ns = datetime_to_ns(end_time)\n", + "timestamps = np.arange(start_ns, end_ns, 1e9 / 30, dtype=\"int\")" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": {}, + "outputs": [], + "source": [ + "# Get the original loads\n", + "load, load_names = sims.get_loads()\n", + "nloads = len(load_names)\n", + "\n", + "# Generate the randomized scaling factors\n", + "mu = 1.1\n", + "sig = 0.1\n", + "s = np.random.normal(loc=mu, scale=sig, size=[nloads, T])\n", + "\n", + "# Generate the new load values\n", + "new_load = s * load[:, np.newaxis]" + ] + }, + { + "cell_type": "code", + "execution_count": 154, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running simulation: 0%| | 0/1799 [00:00]" + ] + }, + "execution_count": 155, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(timestamps, V[\"646/VCM\"])\n", + "plt.plot(timestamps, V[\"646/VBM\"])\n", + "\n", + "plt.figure()\n", + "plt.plot(timestamps, V[\"646/VCA\"])\n", + "plt.plot(timestamps, V[\"646/VBA\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of streams simulated:\n", + "234\n" + ] + } + ], + "source": [ + "print(\"Number of streams simulated:\")\n", + "print(len(V.keys()) + len(I.keys()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Push data to streams" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Put voltage data into the corresponding stream\n", + "sims.add_all_data(timestamps, V, streams_dict, prefix)\n", + "# Put current data into the corresponding stream\n", + "sims.add_all_data(timestamps, I, streams_dict, prefix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Add long period of data\n", + "The following cell runs a loop which will generate and push data over a much longer period. \n", + "The purpose of the loop is to avoid generating all the data at once - instead, the full time period is divided into smaller time chunks, with data generated and inserted for each chunk sequentially. \n", + "\n", + "The code is divided into two cells below - the first is the initialization step. The second runs the loop. If there is an error during the loop, the second cell can be re-run and will pick up where it left off. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Collection prefix in which data will be added\n", + "prefix = \"simulated/ieee13\"\n", + "# Get the desired output streams to which data will be pushed\n", + "collections, names, tags, annotations = sims.get_stream_info(base_col=prefix)\n", + "# If the desired streams exist, retrieve them. Otherwise create them.\n", + "streams_dict = sims.create_streams(prefix, collections, names, tags, annotations, conn)\n", + "\n", + "\n", + "# Get the original loads\n", + "load, load_names = sims.get_loads()\n", + "nloads = len(load_names)\n", + "\n", + "# Simulation time window - the FULL time range over which we want to generate data\n", + "start_time = datetime(2022, 1, 2, 0, 0, 0)\n", + "end_time = datetime(2022, 1, 3, 0, 0, 0)\n", + "fs = 30 # Hz\n", + "Ttotal = int(((end_time - start_time).total_seconds()) * fs)\n", + "print(\"We will generate\", Ttotal, \"samples.\")\n", + "\n", + "# The simulation time step - this is the amount of data we insert at once.\n", + "step = timedelta(minutes=5)\n", + "nsteps = int((end_time - start_time) / step)\n", + "\n", + "# Create progress bar\n", + "pbar = tqdm(total=nsteps, desc=\"Adding simulated data\")\n", + "\n", + "t0 = start_time" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c1f55605fad2421f944ee0fc466c5752", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Adding simulated data: 0%| | 0/110 [00:00" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "T = 100 # Number of time points to simulate\n", + "\n", + "# Get the original loads\n", + "load, load_names = sims.get_loads()\n", + "nloads = len(load_names)\n", + "\n", + "# Generate the randomized scaling factors\n", + "mu = 1.1\n", + "sig = 0.1\n", + "s = np.random.normal(loc=mu, scale=sig, size=[nloads, T])\n", + "\n", + "# Generate the new load values by scaling the original loads with randomized s\n", + "new_load = s * load[:, np.newaxis]\n", + "\n", + "# Visualize some of the load curves\n", + "plt.plot(new_load[0:5, :].T);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now to iteratively run the simulation for each load setting and retrieve the resulting voltages and currents...\n", + "\n", + "The function `simulate_network` does this all for you. It has the signature `simulate_network(loads, load_names, contypes=['Line', 'Transformer'])`. The first argument is the desired load values in an $n\\times T$ matrix (as created above), where $n$ is the number of loads we want to set. The second argument is the names of the loads to set (as returned by `get_loads()` above). Finally, the optional argument `contypes` specifies which types of connections we want to return current data for. \n", + "\n", + "The function returns dictionaries of voltage and current, with the sames keys as `v2dict` and `i2dict` respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running simulation: 0%| | 0/99 [00:00" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "key_list = [key for key in V.keys()]\n", + "\n", + "plt.plot(V[key_list[0]])\n", + "plt.title(key_list[0]);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And one of the resulting current magnitudes. " + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "key_list = [key for key in I.keys()]\n", + "\n", + "plt.plot(I[key_list[0]])\n", + "plt.title(key_list[0]);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/source/conf.py b/docs/source/conf.py index d44492a..0d72cc9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,8 +1,10 @@ +# -*- coding: utf-8 -*- +# # Configuration file for the Sphinx documentation builder. # -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- @@ -17,17 +19,21 @@ import os import sys -sys.path.insert(0, os.path.abspath("../..")) +import btrdbextras -import sphinx_glpi_theme +sys.path.insert(0, os.path.abspath("_themes")) +sys.path.insert(0, os.path.abspath("../..")) # -- Project information ----------------------------------------------------- project = "btrdbextras" -copyright = "2020, PingThings, Inc." +copyright = "2023, PingThings, Inc." author = "PingThings, Inc." - +# The short X.Y version +version = btrdbextras.__version__ +# The full version, including alpha/beta/rc tags +release = version # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -36,18 +42,39 @@ extensions = [ "sphinx.ext.autodoc", "sphinx.ext.napoleon", + "sphinx.ext.todo", "sphinx.ext.githubpages", "sphinx.ext.intersphinx", + "numpydoc", ] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ["build", "Thumbs.db", ".DS_Store"] +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + # -- Options for HTML output ------------------------------------------------- @@ -56,6 +83,78 @@ # -html_theme = "glpi" +html_theme = "alabaster" +# html_theme = "sphinx_rtd_theme" +html_theme = "pydata_sphinx_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = { + "show_powered_by": False, + "github_user": "PingThingsIO", + "github_repo": "btrdbextras", + "travis_button": False, + "github_banner": False, + "show_related": False, + "note_bg": "#FFF59C", + "description": "An additional library of enhancements and features to " + "interact with the BTrDB database and Pingthings platform.", + "extra_nav_links": {"btrdb": "http://btrdb-python.readthedocs.io"}, + "show_relbars": True, +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = { +# '**': [ +# 'sidebar.html', +# 'localtoc.html', +# 'relations.html', +# 'searchbox.html', +# ], +# } + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = "btrdbextras" + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ["search.html"] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True -html_theme_path = sphinx_glpi_theme.get_html_themes_path() +numfig = True From 8f9f4ddab3d33ded9d16e4653c1c818c57e7dbd8 Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:08:14 -0800 Subject: [PATCH 09/10] remove opendss notebooks added, in separate PR --- .../IEEE_13_-_Create_Streams_Add_Data.ipynb | 5042 ----------------- .../Intro_to_Simulation_with_OpenDSS.ipynb | 405 -- 2 files changed, 5447 deletions(-) delete mode 100644 btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb delete mode 100644 btrdbextras/opendss_ingest/Intro_to_Simulation_with_OpenDSS.ipynb diff --git a/btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb b/btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb deleted file mode 100644 index f0ec190..0000000 --- a/btrdbextras/opendss_ingest/IEEE_13_-_Create_Streams_Add_Data.ipynb +++ /dev/null @@ -1,5042 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 146, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "import opendssdirect as dss\n", - "import matplotlib.pyplot as plt\n", - "from tqdm.notebook import tqdm_notebook, tqdm\n", - "import btrdb as db\n", - "import uuid\n", - "from btrdb.utils.timez import datetime_to_ns\n", - "import simulation_utils as sims\n", - "from datetime import datetime, timedelta\n", - "\n", - "%matplotlib inline\n", - "\n", - "import importlib\n", - "\n", - "importlib.reload(sims);" - ] - }, - { - "cell_type": "code", - "execution_count": 147, - "metadata": {}, - "outputs": [], - "source": [ - "# Connect to the database\n", - "conn = db.connect(profile=\"collab\")" - ] - }, - { - "cell_type": "code", - "execution_count": 148, - "metadata": {}, - "outputs": [], - "source": [ - "model_loc = \"./Models/13Bus/IEEE13Nodeckt.dss\"\n", - "dss.run_command(\"Redirect \" + model_loc);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Create output streams\n", - "The following cells create the output streams or retrieve them if they have already been created. " - ] - }, - { - "cell_type": "code", - "execution_count": 149, - "metadata": {}, - "outputs": [], - "source": [ - "prefix = \"simulated/ieee13\"\n", - "collections, names, tags, annotations = sims.get_stream_info(base_col=prefix)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nstreams = len(collections)\n", - "print(\"Creating\", nstreams, \"streams\")\n", - "for i in range(nstreams):\n", - " print(collections[i] + \"/\" + names[i])" - ] - }, - { - "cell_type": "code", - "execution_count": 151, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Found 234 streams under simulated/ieee13\n", - "Found 234 streams. Created 0 streams.\n" - ] - } - ], - "source": [ - "streams_dict = sims.create_streams(prefix, collections, names, tags, annotations, conn)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate simulated measurements\n", - "The following cell generates data that will be converted into streams. \n", - "For convenience, we back-calculate the number of samples from a user specified sample rate (`fs`) and simulation duration (`start_time` to `end_time`). However, keep in mind that the simulation has no inherent sense of time - we are abitrarily assigning timestamps to each simulation result. " - ] - }, - { - "cell_type": "code", - "execution_count": 152, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "We will generate 1800 samples.\n" - ] - } - ], - "source": [ - "# The number of samples to generate\n", - "start_time = datetime(2022, 1, 1, 0, 0, 0)\n", - "end_time = datetime(2022, 1, 1, 0, 1, 0)\n", - "fs = 30 # Hz\n", - "T = int(((end_time - start_time).total_seconds()) * fs)\n", - "print(\"We will generate\", T, \"samples.\")\n", - "\n", - "# Generate the nanosecond timestamps for the data\n", - "start_ns = datetime_to_ns(start_time)\n", - "end_ns = datetime_to_ns(end_time)\n", - "timestamps = np.arange(start_ns, end_ns, 1e9 / 30, dtype=\"int\")" - ] - }, - { - "cell_type": "code", - "execution_count": 153, - "metadata": {}, - "outputs": [], - "source": [ - "# Get the original loads\n", - "load, load_names = sims.get_loads()\n", - "nloads = len(load_names)\n", - "\n", - "# Generate the randomized scaling factors\n", - "mu = 1.1\n", - "sig = 0.1\n", - "s = np.random.normal(loc=mu, scale=sig, size=[nloads, T])\n", - "\n", - "# Generate the new load values\n", - "new_load = s * load[:, np.newaxis]" - ] - }, - { - "cell_type": "code", - "execution_count": 154, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Running simulation: 0%| | 0/1799 [00:00]" - ] - }, - "execution_count": 155, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX8AAAEFCAYAAAAL/efAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAfWUlEQVR4nO3deXRcZ5nn8e9TpVJpt3ZLtuzIWxI7gWwiJOwhLCENBJqlA2eYDNCTPjPAwOHMzIFhZrr7dNNDz2GYbjjd9GQgEM4AYZsM6SadlZCEJSR2Vju2Y9nxJkuWrH0vqeqZP97rRHG8xZZcsd7f55w6qnrvrXufe2/pp7du3Xpl7o6IiMQlVewCRETkzFP4i4hESOEvIhIhhb+ISIQU/iIiESopdgEno7Gx0dvb24tdhojIWWXTpk2H3L3paNPOivBvb29n48aNxS5DROSsYmZ7jjVNp31ERCKk8BcRiZDCX0QkQgp/EZEIKfxFRCKk8BcRiZDCX0QkQmfFdf6nY2omT/94jk17BqmryNBWV8GBoUnSKWN9aw1bDgwzmctTU56ha3CSskyKtc3VPNM9whWr6smkU+TdyZakGByfoSRt/G5nP3WVGQoFWNtcxcGRKUamZmmpKSObSdGypIz7t/UykcvzujUN7O6foHVJGdt7RjmvpZr+sRzDkzlKUmHeitI0swUnk07h7hQcOntHaauroG9smpaaMnqGpygtSbFuaRX9YzmGJmZIGaxprmJ7zyjLa8vZ0TtGfWWGLQdGaKkpo7ailNYlZYxNz9LeUMmhsWn6x3MsrcnSMzzF5gMjlKaNVY1VnN9aTc/wFF2Dk1y6so6+sSn6x3IcGstRXVZCyoxtPSOsqK9g2ZJydvSOsqQ8w0y+QLYkTVkmzXkt1XQPT2IYM/kC+wYnmJjO01ZfTnN1GZO5PL2jUwxOzDCbL3DJyjo6e8dY01xJSSpF9/AkzdVl5GYL1FaEZQM8vGuAwYkcV69vplCAusoMaTMe3zdEeSZNU3WW4ckZ1jVXMTgxQ2U2TdfgJAPjOc5vqaHgTqYkRdqMwYkcbXXlHByZJmXQVJ3l6f3DtNVVcO/Wg9RWZJgtOMtry2muzjI5k2dJeYYDQ1M0VJVSU5ahf3wadxiZmmF1YxWP7R3k4hW1pFPGo7sHuHDZEtIpo388R1kmxejULAPjOdY0VfHYnkGuXNNAJp3i8b2DdA1N8vYNS+kanGRlQwX7ByeZzTsbltUwWyjQPTTFwESOhspSVtRVUF6apuDO1u4RDo5MU19ZSltdOZO5PDv7xmmqLqW5uoz+8RytS8q4d+tBKkrTpFMpapLj2FBVytRMgaU1Wfb0T9BWV05JOkX/2DT5grOrb5wV9RU8tX+Itc1VtCwpoySVIp0yBsanqcyWUJoOj3/deYjGqiyXrKzFHeoqSim4MzY9y/7BSVY1VrL70DgpM+oqM+w+NMGhsWmGJ2d43ZoGBidmqChNMzWTp7QkxdRMgZaaMlIpODSWoyqbZmqmwDkNFQyM59jVN05jVZa2unI6+8bYPzjBkvIMK+sr2XJgmCtXN5DNpDGDTCrF6PQM9zxzkGsvbOWBZ/u4dGUdrbVlTM3kmZopsLV7hLJMmnQKZvLO2NQs65fVMDNbYGhyhoI71dkSekenKbjTuqScoYkcTdVZfruzn9e019M9PMnlq+r5zm92s761hnyhQGVpCWubq+gamqQyW4K7M5krhOWVlXBgaAqAimyaiek8m/YM8vq1DewdmCBlxuvWNNDZN0Z1NsP5rdVk0vPfT7ezYTz/jo4OP5UvefWOTHHN3z7EwHhuAaoSEVl4V6yu5/t/fAXplL3s55rZJnfvONq0Rd3zLytNs665iq3dI4xMzQJwycpaHt879Pw8y2vLGZ2aeX76Yc3VWXpHpwEoTadoqy+nZ3iKS1fWsfnAMEMTM5zTUMHSmjIyaePgyDQlKeOCZUsA2Dc4waO7B7jhynYKyR/YO57u4co1DQyMT/Po7kGy6RTXXbKM6rIMOw6OkkmnqK8s5an9wzzdNfx8LZeurKUsk+a3O/u5YFkN7Y2VPLyzn/45f9QuWVnL6NQsa5oqGZ/Oc35LNdsPjvLQjkOsaqzkuUPjALx9w1Ke2j/E+HSe3GyB9ctqeHLfC/tjdVMla5uqmJot8PCufgCuXN1Ac3WWn2zaz+rGStrqK3jw2b6wjzMpltWWky84zdXZ59/BNFdnKU2neODZPl63tpHnDo2xuWsEIHlXkqEqW8LGPYM0VmVpb6hg16FxGqtKGZ/O0zU0yR91rGBoMse2nlHSZmQzada3VnP3loMU3GmoKqWsJE1FtoSykhQTuTy7+sYYz+Wf354rVzfwu139VGdL+NRb17Jx9wD5gnP/9lB/RWmaiVyet61vZnf/BC01Zfy689Dzz//MW9fy2N5BuoemWL+shkOj02zaM0hZJk15aZp3v7qVR3cP0FJTzkM7+rh6fTPZkjQXLl/C1+7eTt6d2bwzW3A++tqVbOseIe/QWlPG8OQMTdVZHts7yPDkDNde2Mptj3eRyxe4+vxmKrIlzMwWKEkbnb1jbOsZBeD8lmpy+QJtdRUMjufoHZ2iPJNmeHKGpTWhV3vZOfWc01DBd3+7m7GpWXL5AuctraZnZIrhyRkAGipLKcukyWZSVJSmGZ2apbk6y6O7B0lZeFe7tKaMNU1V7OgdZWB8hitW13Pf1l7Ob6mmtiLDbY938Zr2egruPLxrgDef20RutkC+4GBhHfdv72VqpsDK+gq6hiYpTaeYnMnzRx0reGzvIDt6xwC4YFkNLTVlFDwcn9WNlayor+DQ2DTdw1PPd+I+3NHGyOQsD+3oe/5Yl6SM8mQb1jZXcdV5TXQPTzGbd+7c0kPKoOCwsr6C9sZKmqqy/HLbQeoqS+kbnWZJeYZCwTkwHHrkpSUpcrOF5+va2TfG1EyBN5/bxOauYSqzJewdmOD8lmpGJmfI5QscGsuxvrWGmrISfv/cAE3VWfpGp7lidT3dw1Ps6Z8AoL6ylGW1ZWzuGuEPXtVK39g0Ww+M8G+uWsPmrmF+v2uADctq6BqaZF1zFW9Y13RKwX8ii7rnLyISs+P1/PWBr4hIhBT+IiIRUviLiERI4S8iEiGFv4hIhBT+IiIRUviLiERI4S8iEiGFv4hIhOYl/M3sZjPrNbPNc9rqzeweM9uR/KxL2s3Mvm5mnWb2lJldOh81iIjIyZuvnv93gWuOaPsCcJ+7rwPuSx4DvAtYl9xuBL45TzWIiMhJmpfwd/cHgYEjmq8Dbknu3wK8b0779zx4GKg1s9b5qENERE7OQp7zX+ru3cn9HmBpcn85sG/OfPuTthcxsxvNbKOZbezr61vAMkVE4nNGPvD1MHToyxo+1N1vcvcOd+9oampaoMpEROK0kOF/8PDpnORnb9LeBayYM19b0iYiImfIQob/7cANyf0bgJ/Paf+XyVU/VwDDc04PiYjIGTAv/8nLzH4IvAVoNLP9wJ8CXwF+bGafBPYAH05mvwO4FugEJoCPz0cNIiJy8uYl/N39I8eYdPVR5nXgU/OxXhEROTX6hq+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhKhkoVegZntBkaBPDDr7h1mVg/8CGgHdgMfdvfBha5FRESCM9Xzv8rdL3b3juTxF4D73H0dcF/yWEREzpBinfa5DrgluX8L8L4i1SEiEqUzEf4O3G1mm8zsxqRtqbt3J/d7gKVHPsnMbjSzjWa2sa+v7wyUKSISjwU/5w+8wd27zKwZuMfMts2d6O5uZn7kk9z9JuAmgI6OjpdMFxGRU7fgPX9370p+9gK3AZcDB82sFSD52bvQdYiIyAsWNPzNrNLMqg/fB94BbAZuB25IZrsB+PlC1iEiIi+20Kd9lgK3mdnhdf3A3e80s0eBH5vZJ4E9wIcXuA4REZljQcPf3XcBFx2lvR+4eiHXLSIix6Zv+IqIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhFS+IuIREjhLyISIYW/iEiEFP4iIhEqWvib2TVmtt3MOs3sC8WqQ0QkRkUJfzNLA38HvAvYAHzEzDYUoxYRkRgVq+d/OdDp7rvcPQfcClxXpFpERKJTrPBfDuyb83h/0vY8M7vRzDaa2ca+vr4zWpyIyGL3iv3A191vcvcOd+9oamoqdjkiIotKscK/C1gx53Fb0iYiImdAscL/UWCdma0ys1LgeuD2ItUiIhKdkmKs1N1nzezTwF1AGrjZ3bcUoxYRkRgVJfwB3P0O4I5irV9EJGav2A98RURk4Sj8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEIKfxGRCCn8RUQipPAXEYmQwl9EJEILFv5m9mdm1mVmTyS3a+dM+6KZdZrZdjN750LVICIiR1eywMv/n+7+1bkNZrYBuB64AFgG3Gtm57p7foFrERGRRDFO+1wH3Oru0+7+HNAJXF6EOkREorXQ4f9pM3vKzG42s7qkbTmwb848+5O2FzGzG81so5lt7OvrW+AyRUTiclrhb2b3mtnmo9yuA74JrAEuBrqB//Fylu3uN7l7h7t3NDU1nU6ZIiJyhNM65+/ubzuZ+czsfwP/lDzsAlbMmdyWtImIyBmykFf7tM55+H5gc3L/duB6M8ua2SpgHfDIQtUhIiIvtZBX+/x3M7sYcGA38CcA7r7FzH4MPAPMAp/SlT4iImfWgoW/u3/sONO+DHx5odYtIiLHp2/4iohESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiETqt8DezD5nZFjMrmFnHEdO+aGadZrbdzN45p/2apK3TzL5wOusXEZFTc7o9/83AHwIPzm00sw3A9cAFwDXA35tZ2szSwN8B7wI2AB9J5hURkTOo5HSe7O5bAczsyEnXAbe6+zTwnJl1Apcn0zrdfVfyvFuTeZ85nTpEROTlWahz/suBfXMe70/ajtX+EmZ2o5ltNLONfX19C1SmiEicTtjzN7N7gZajTPqSu/98/ksK3P0m4CaAjo4OX6j1iIjE6ITh7+5vO4XldgEr5jxuS9o4TruIiJwhC3Xa53bgejPLmtkqYB3wCPAosM7MVplZKeFD4dsXqAYRETmG0/rA18zeD3wDaAJ+YWZPuPs73X2Lmf2Y8EHuLPApd88nz/k0cBeQBm529y2ntQUiIvKymfsr/3R6R0eHb9y4sdhliIicVcxsk7t3HG2avuErIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIQU/iIiETqtgd1e8fIzsPsh2HYHDO2Biz8K/Tth4Dkwg6lhaHkVYFC7EsZ7YXII8jnIjUNdO3Q/AZlysBRka6AwC8sugYOb4dm74LKPQzoDEwMwMw7ZaliyAnbeD+N9YflN50HPZlj52vD8nb+EqqVhnZOD0PVYWH66FLwAo91wcAuU1cDrPwvVrXDo2dBWsyzUtuNuWPdOaFgDZUvCusZ6w3Lz02E7SrLQtB56n4G9D4ftWXs1VLfArgfCz7GDsPd3UL8mLCNTAfWrYPxQWPbIAZiZCPVNj8LsFFQvAzy0r7gCep4O66pfBSVlYZt2/Srsh8lBqKgP25StCetbfhksuzS0mcFsDkYPQMPacNz6O+G5B2FJG1Q0wOx02FdN54fj2P1U2E9rrgo/x/rC88d6w75ZfmnYT73bwv4uKYNH/heseC24Q2lF2HfZqrDs0kp4+iehrsZzw7bmxuHQdsguCcd1aiQsq2ENjPZA7Tlh3b1bwj7LVMDG78Db/yy8rkYPhu3Gwn72QriVVsH0cHgdjvXC1BBsuA5SJWFfl1aF11vfdiivC/dHusJ+m5mCPb8J+2xyEFZeCSuvgIFd4TVQyEPrReF10nReOIbNG2Drz8NzV1wOg7tf2J9LlsPvbwr7uDADLa8O7bUr4MATsO0XYZ9UNoZtXnF5eA24h33y9M/gouvDvp6ZCPsIIDcW9uPQ3vCaWnYJTPRDZVPY3kM7oHk9lNeHbdn+zzA9Aue8Hnq3hlpGe0I95bXh9V+1FAafg99+I7wOGteF11DPU2H/5iagpjX8HvY8HequqA/HtaolrH/NVeFnbiIcI0uF3/VD22Hpq8IyG88N9Tz5A1h9VailZnl4rbZeFF6juQkY3hfaceh+Evb8Dt74edh1f6hh2cWQyoTXXkk2ZMSuB2DHXbD0wrD+1/278LiiAS54f8iIsZ7w/MZzIVMWjmHT+XDpx+Y9Hhf3wG5jffDVtfNfkIjImdJ6EfzJgyee7yiON7Db4u75ly2Bj98ZepFdm17oDYx0hd5E/87QA8lUhN6fpULvbKQr9C7Xvyf89R3rC9OH94flVjaEnvXIgdA7a1wX/lpPDYXpSy+A/RuhqhnqVye9twOhV5XKwIHHQ2981ZtCT6yQDz2cmUnY/DNoe02Yf3IAXvXhsI6hPWE7NlwHT/4wtG24LtQ7PRp6XTPj4X4qE95FNJ8PjeeFdQ3tDb3Hde8I8wztDfOnS2HfI2E/tF4cpqUzoZfW81To1Q13hZ5XZSNsvT3Mc+EHQnvtSjj4NBx8BtpfH3pZs1NhmdUtSW95baiza1P4Wd0Sen1De8MxGd4Xej9ltTCU7I+GteEdQMMaePJH4TkV9ZCphO13gOfDc1svCr3moX2hN1W7MmzL9Eiob3Ig9L76d8KK14R9M5304uvaQy/W8+HYlteH2uvaQ49raG847gM7Q4/0wg+E+bufDL3m+tUvHPfCbHinUVYT3rGUVoV3gTMTgIX93HkPpLPQdlnoiU8Nhddoy6tC+8Sh0MNsWAebvht69v07wuuzuiXMm58Jr7H9j4Qe4ao3hXcJEwMvvHsaPQhtHdC1MfRo89PhnczkUNh31S1hH9Wtgk3fgbVvD22WCstPZ8Ix6HkqvIPITYRjV9ce9m9pZXjXUlH/wnEqqw3bWtUc3uEN7IS+Z0PPfs1V4fepbEnYvtGe8C4slQ7vUrb/M6x/d9iu3m2w7u1hfw3sCutMlYR14tB5X9ivzetDDcP7w/FsWBtev6l0eGcz3hfe4ZfXhtfQ0N4wfaI/LG/3r8PP6qXhtdN4bpjXPbxzKK8Nv2OF2bA9h7aH+jOVoa3n6fB7vmR5eK2P9kD7G8I+S2fDvAe3hGNbvTS0jR0M+xgPr4/KRnj2bkiXhGO26o0wcvjd8FQ4FiteG35nF8Di7vmLiERMQzqLiMiLKPxFRCKk8BcRiZDCX0QkQgp/EZEIKfxFRCKk8BcRiZDCX0QkQmfFl7zMrA/YcxqLaAQOzVM5xbRYtgO0La9Ui2VbFst2wOltyznu3nS0CWdF+J8uM9t4rG+5nU0Wy3aAtuWVarFsy2LZDli4bdFpHxGRCCn8RUQiFEv431TsAubJYtkO0La8Ui2WbVks2wELtC1RnPMXEZEXi6XnLyIicyj8RUQitKjD38yuMbPtZtZpZl8odj2nysxuNrNeM9tc7FpOl5mtMLP7zewZM9tiZp8tdk2nyszKzOwRM3sy2ZY/L3ZNp8PM0mb2uJn9U7FrOR1mttvMnjazJ8zsrP4vUGZWa2Y/NbNtZrbVzK6ct2Uv1nP+ZpYGngXeDuwHHgU+4u7PFLWwU2BmbwLGgO+5+4XFrud0mFkr0Oruj5lZNbAJeN9ZelwMqHT3MTPLAL8GPuvuDxe5tFNiZp8HOoAad393ses5VWa2G+hw97P+S15mdgvwkLt/y8xKgQp3H5qPZS/mnv/lQKe773L3HHArcF2Razol7v4gMFDsOuaDu3e7+2PJ/VFgK7C8uFWdGg/GkoeZ5HZW9qbMrA34A+Bbxa5FAjNbArwJ+DaAu+fmK/hhcYf/cmDfnMf7OUtDZrEys3bgEuD3RS7llCWnSp4AeoF73P1s3Za/Af4jUChyHfPBgbvNbJOZ3VjsYk7DKqAP+E5yOu5bZlY5XwtfzOEvr2BmVgX8DPicu48Uu55T5e55d78YaAMuN7Oz7rScmb0b6HX3TcWuZZ68wd0vBd4FfCo5bXo2KgEuBb7p7pcA48C8fXa5mMO/C1gx53Fb0iZFlpwf/xnwfXf/v8WuZz4kb8fvB64pcimn4vXAe5Nz5bcCbzWz/1Pckk6du3clP3uB2wingM9G+4H9c95N/pTwx2BeLObwfxRYZ2arkg9KrgduL3JN0Us+JP02sNXdv1bsek6HmTWZWW1yv5xwccG2ohZ1Ctz9i+7e5u7thN+TX7r7vyhyWafEzCqTCwlITpG8Azgrr5Jz9x5gn5mdlzRdDczbhREl87WgVxp3nzWzTwN3AWngZnffUuSyTomZ/RB4C9BoZvuBP3X3bxe3qlP2euBjwNPJuXKA/+TudxSvpFPWCtySXFmWAn7s7mf1ZZKLwFLgttDHoAT4gbvfWdySTstngO8nHdhdwMfna8GL9lJPERE5tsV82kdERI5B4S8iEiGFv4hIhBT+IiIRUviLROTlDBJoZm8ys8fMbNbMPnjEtBvMbEdyu+FlrP+YyzxivlIzu8nMnk0GNfvAEdM/YGZuZh1z2r6YDOK43czeOaf9s2a2ORl873Nz2i8ys98lg8D9o5nVJO3tZjaZDAz3hJn9Q9JeYWa/SOrZYmZfmbOsrJn9KFn/75Nvr5+orpc18KSZfShZb+GI7c6Y2S3Jdmw1sy+eaFkAuLtuuukWyY0wVsylwOaTmLcdeDXwPeCDc9rrCZcd1gN1yf26ozz3Vye7zKPM9+fAXyb3U0DjnGnVwIPAw4QB3AA2AE8CWcKwCDsJl3hfSLjOv4Jw6ee9wNrkOY8Cb07ufwL4izk1vmT/JMu4KrlfCjwEvCt5/G+Bf0juXw/86AR1pZP7q5NlPQlsOMHxWA+cB/zq8HYn7R8Fbp1T426g/UTHVz1/kYj4UQYJNLM1ZnZnMhbOQ2Z2fjLvbnd/ipeO9/NOwjhGA+4+CNzDSX6z+TjLPNIngP+WPKfgLx6h8y+Avwam5rRdRwjAaXd/DugkfLN3PfB7d59w91ngAeAPk+ecS/gjQrINL3p3cZTaJ9z9/uR+DniMMHLA4fXfktz/KXB18oXGY9V1zIEnzewyM3sgOR53JSPh4u5b3X370UoDKs2sBCgHcsAJh0xR+IvITcBn3P0y4N8Df3+C+Rd00MTD35oG/iI5RfQTM1uaTLsUWOHuvzjJmjYDbzSzBjOrAK7lhWFftvDCSL8f4sXDwaxKBlN7wMzeeIwa3wPcd+T6kz8yw0DDceo6ansy9Mk3CO+KLgNuBr78kp30Yj8ljPvTDewFvuruJxwFeNF+w1dETiwZYO91wE+Sb8VCOEVxqsu7jXB6oxRYOedb3H/r7t85ycWUEHrUv3X3z1v4PwNfTT5b+Brwr062HnffamZ/DdxNCMgngHwy+RPA183svxCGfskl7d3ASnfvN7PLgP9nZhd4MgBh0sP+IfB1d991srWcpPMIp6ruSY5HOqnneC4nbNMywmm4h8zs3hPVpvAXiVsKGPIwMunJ6iIMN3JYG+E8NO7+fnh+uO7vuvtbePn6gQng8KB/PwE+STjXfyHwqyQYW4Dbzey9HGcgRw9DoXw7qeuvCL1s3H0bYewfzOxcwv8zwN2ngenk/iYz20k4RXT4v4LdBOxw97+Zs77D69+f/HFYkmzH8QaYPFq7AVvc/eX8x66PAne6+wzQa2a/IfxTnuOGv077iEQs6c0+Z2YfgjDwnplddIKn3QW8w8zqzKyOEKB3zWNNDvwjL/yBuRp4xt2H3b3R3ds9DEL3MPBed99I6Llfn1x1swpYBzySbFNz8nMl4Xz/D45oTwH/GTh8VU+ThfGaMLPVybJ2JY//khDsnzui7NuBw1c9fZAwOJ4fp65jDTy5HWiy5N81JlfyXHCCXbYXeGsyfyVwBSczwOB8XEGgm266nR03wumKbmCG0AP+JOE0zZ2EK06eAf5rMu9rknnGCb3YLXOW8wnCh5edwMePsp52jn61z/GW+cSc++cQPox9inBefeVRlvUrXnzVy5cIV9BsJ7kKJ2l/KNmuJ4Gr57R/lvCvXp8FvsILY519gPB5wBOED3Xfk7S3ET5c3ZpMewL442RaGeEdSich3FefRF3XJuveCXxpTvvFybY/mdTxr5P29yf7bho4CNyVtFcl696SbOd/OJnXggZ2ExGJkE77iIhESOEvIhIhhb+ISIQU/iIiEVL4i4hESOEvIhIhhb+ISIT+P7A3ohNGhhObAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(timestamps, V[\"646/VCM\"])\n", - "plt.plot(timestamps, V[\"646/VBM\"])\n", - "\n", - "plt.figure()\n", - "plt.plot(timestamps, V[\"646/VCA\"])\n", - "plt.plot(timestamps, V[\"646/VBA\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 156, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of streams simulated:\n", - "234\n" - ] - } - ], - "source": [ - "print(\"Number of streams simulated:\")\n", - "print(len(V.keys()) + len(I.keys()))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Push data to streams" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Put voltage data into the corresponding stream\n", - "sims.add_all_data(timestamps, V, streams_dict, prefix)\n", - "# Put current data into the corresponding stream\n", - "sims.add_all_data(timestamps, I, streams_dict, prefix)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Add long period of data\n", - "The following cell runs a loop which will generate and push data over a much longer period. \n", - "The purpose of the loop is to avoid generating all the data at once - instead, the full time period is divided into smaller time chunks, with data generated and inserted for each chunk sequentially. \n", - "\n", - "The code is divided into two cells below - the first is the initialization step. The second runs the loop. If there is an error during the loop, the second cell can be re-run and will pick up where it left off. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Collection prefix in which data will be added\n", - "prefix = \"simulated/ieee13\"\n", - "# Get the desired output streams to which data will be pushed\n", - "collections, names, tags, annotations = sims.get_stream_info(base_col=prefix)\n", - "# If the desired streams exist, retrieve them. Otherwise create them.\n", - "streams_dict = sims.create_streams(prefix, collections, names, tags, annotations, conn)\n", - "\n", - "\n", - "# Get the original loads\n", - "load, load_names = sims.get_loads()\n", - "nloads = len(load_names)\n", - "\n", - "# Simulation time window - the FULL time range over which we want to generate data\n", - "start_time = datetime(2022, 1, 2, 0, 0, 0)\n", - "end_time = datetime(2022, 1, 3, 0, 0, 0)\n", - "fs = 30 # Hz\n", - "Ttotal = int(((end_time - start_time).total_seconds()) * fs)\n", - "print(\"We will generate\", Ttotal, \"samples.\")\n", - "\n", - "# The simulation time step - this is the amount of data we insert at once.\n", - "step = timedelta(minutes=5)\n", - "nsteps = int((end_time - start_time) / step)\n", - "\n", - "# Create progress bar\n", - "pbar = tqdm(total=nsteps, desc=\"Adding simulated data\")\n", - "\n", - "t0 = start_time" - ] - }, - { - "cell_type": "code", - "execution_count": 145, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c1f55605fad2421f944ee0fc466c5752", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Adding simulated data: 0%| | 0/110 [00:00" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "T = 100 # Number of time points to simulate\n", - "\n", - "# Get the original loads\n", - "load, load_names = sims.get_loads()\n", - "nloads = len(load_names)\n", - "\n", - "# Generate the randomized scaling factors\n", - "mu = 1.1\n", - "sig = 0.1\n", - "s = np.random.normal(loc=mu, scale=sig, size=[nloads, T])\n", - "\n", - "# Generate the new load values by scaling the original loads with randomized s\n", - "new_load = s * load[:, np.newaxis]\n", - "\n", - "# Visualize some of the load curves\n", - "plt.plot(new_load[0:5, :].T);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now to iteratively run the simulation for each load setting and retrieve the resulting voltages and currents...\n", - "\n", - "The function `simulate_network` does this all for you. It has the signature `simulate_network(loads, load_names, contypes=['Line', 'Transformer'])`. The first argument is the desired load values in an $n\\times T$ matrix (as created above), where $n$ is the number of loads we want to set. The second argument is the names of the loads to set (as returned by `get_loads()` above). Finally, the optional argument `contypes` specifies which types of connections we want to return current data for. \n", - "\n", - "The function returns dictionaries of voltage and current, with the sames keys as `v2dict` and `i2dict` respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 76, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Running simulation: 0%| | 0/99 [00:00" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "key_list = [key for key in V.keys()]\n", - "\n", - "plt.plot(V[key_list[0]])\n", - "plt.title(key_list[0]);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And one of the resulting current magnitudes. " - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "key_list = [key for key in I.keys()]\n", - "\n", - "plt.plot(I[key_list[0]])\n", - "plt.title(key_list[0]);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From fdefa9cc9b3c53540781000e6d1b03eba2248421 Mon Sep 17 00:00:00 2001 From: Jeff Lin <42981468+jleifnf@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:09:49 -0800 Subject: [PATCH 10/10] disable actions for draft PR and add coverage report in test-suite --- .github/workflows/release.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8951694..2a9fd4e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,6 +11,7 @@ on: jobs: test-suite: + if: github.event.pull_request.draft == false runs-on: ${{ matrix.os }} strategy: matrix: @@ -30,7 +31,10 @@ jobs: pip install -r tests/requirements.txt - name: Test with pytest run: | - pytest + pytest --cov-report= --cov=btrdbextras # suppress coverage report here + - name: Coverage Report + run: | + coverage report -m release: