Skip to content

Commit

Permalink
Exceptions: Move to separate module, New hierarchy
Browse files Browse the repository at this point in the history
- Module structure following example from NetworkX and other projects.
  This adds an `import pydot` to `core.py`, which is cyclic/circular,
  but necessary to make the exceptions available. Cyclic imports are
  not uncommon and Python can handle this. Using the exceptions in
  pydot source code now requires prefixing `pydot.`, for example:

      raise pydot.Error("Message")

- Exception hierarchy changes. See ChangeLog and class docstrings in
  this commit for details. Additional background notes:

  - Removal of the unused exception class `InvocationException`: It was
    introduced in 842173c of 2008 (v1.0.2), but got in disuse when
    commits 9b3c1a1 and bc639e7 of 2016 (v1.2.0) fell back to using
    `Exception` and `assert` (`AssertionError`) again. If we ever need
    a custom class like this again in the future, it would probably
    have a different signature for context data (e.g. a DOT string,
    input and output), different parent class (or classes, e.g.
    `PydotException, CalledProcessError`) and perhaps a different name
    (e.g. ending in `...Error`), so no need to keep the old class
    around for that.

Further additions to the exception hierarchy are likely before the
final release of pydot 2.0.

Discussed in pydot#171, pydot#230 and pydot#271.
  • Loading branch information
peternowee committed Jul 30, 2021
1 parent f250d65 commit 90936e7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 23 deletions.
10 changes: 9 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Changed:
`-- dot_parser.py |-- __init__.py
|-- core.py
|-- dot_parser.py
`-- ...
`-- exceptions.py

This is mostly an internal change that should go unnoticed by most
users, especially those upgrading through `pip` or a software
Expand Down Expand Up @@ -52,6 +52,14 @@ Changed:
no effect except for printing a deprecation warning. It will be
removed in a future major release (pydot 3 or higher), then
leading to an error.
- Reorganized exception hierarchy: (#230)
- New base class `PydotException`, derived from Python's `Exception`.
- Pydot's `Error` exception class is now derived from `PydotException`
instead of from Python's built-in `Exception` directly. Existing
handlers should not be affected.
- Exception class `InvocationException` was removed. It has not been
raised by pydot since 2016 (v1.2.0).

- API (minor): Renamed the first parameter of the parser functions
listed below from `str` to `s`. These functions primarily exist for
internal use and would normally be called using positional arguments,
Expand Down
1 change: 1 addition & 0 deletions src/pydot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
__version__ = "2.0.0.dev0"
__license__ = "MIT"

from pydot.exceptions import *
from pydot.core import *
26 changes: 4 additions & 22 deletions src/pydot/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import tempfile
import warnings

import pydot

try:
from pydot import dot_parser
except Exception as e:
Expand Down Expand Up @@ -532,26 +534,6 @@ def create_attribute_methods(self, obj_attributes):
)


class Error(Exception):
"""General error handling class."""

def __init__(self, value):
self.value = value

def __str__(self):
return self.value


class InvocationException(Exception):
"""Indicate problem while running any GraphViz executable."""

def __init__(self, value):
self.value = value

def __str__(self):
return self.value


class Node(Common):
"""A graph node.
Expand Down Expand Up @@ -734,7 +716,7 @@ def __eq__(self, edge):
"""

if not isinstance(edge, Edge):
raise Error("Can not compare an edge to a non-edge object.")
raise pydot.Error("Can not compare an edge to a non-edge object.")

if self.get_parent_graph().get_top_graph_type() == "graph":

Expand Down Expand Up @@ -891,7 +873,7 @@ def __init__(
self.obj_dict["attributes"] = dict(attrs)

if graph_type not in ["graph", "digraph"]:
raise Error(
raise pydot.Error(
(
'Invalid type "{t}". '
"Accepted graph types are: "
Expand Down
22 changes: 22 additions & 0 deletions src/pydot/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Exception classes for pydot."""


class PydotException(Exception):
"""Base class for exceptions in Pydot.
This base class will not be raised directly.
Catch this base class to catch all derived exceptions, though be
aware that pydot may raise Python built-in exceptions or pyparsing
exceptions as well.
"""


class Error(PydotException):
"""General error handling class."""

def __init__(self, value):
self.value = value

def __str__(self):
return self.value

0 comments on commit 90936e7

Please sign in to comment.