diff --git a/conda/conda-reqs.txt b/conda/conda-reqs.txt index e2e2941f6..ec856d966 100644 --- a/conda/conda-reqs.txt +++ b/conda/conda-reqs.txt @@ -15,7 +15,6 @@ keyring>=13.2.1 matplotlib>=3.0.0 msrest>=0.6.0 msrestazure>=0.6.0 -nest_asyncio>=1.4.0 networkx>=2.2 numpy>=1.15.4 pandas>=0.25.0 @@ -30,5 +29,3 @@ setuptools>=40.6.3 statsmodels tqdm>=4.36.1 urllib3>=1.23 -vt-py>=0.5.4 -vt-graph-api>=1.0.1 \ No newline at end of file diff --git a/msticpy/common/exceptions.py b/msticpy/common/exceptions.py index b45959026..3e9084fd5 100644 --- a/msticpy/common/exceptions.py +++ b/msticpy/common/exceptions.py @@ -143,7 +143,7 @@ def _repr_html_(self): l_content, l_type = line if l_type == "title": content += f"

{l_content}

" - if l_type == "uri": + elif l_type == "uri": if isinstance(l_content, tuple): name, uri = l_content else: @@ -155,8 +155,7 @@ def _repr_html_(self): text_line = line.replace("\n", "
") content += f"{text_line}
" - ex_html = "".join((ex_style, div_tmplt.format(content=content))) - return ex_html + return "".join((ex_style, div_tmplt.format(content=content))) def _display_txt_exception(self): """Display text-only version of the exception text.""" @@ -167,7 +166,7 @@ def _display_txt_exception(self): print("-" * len(l_content)) print(l_content) print("-" * len(l_content)) - if l_type == "uri": + elif l_type == "uri": if isinstance(l_content, tuple): print(f" - {': '.join(l_content)}") else: @@ -343,6 +342,44 @@ class MsticpyKqlConnectionError(MsticpyUserError): ) +class MsticpyImportExtraError(MsticpyUserError): + """Exception class for Imports that need an extra.""" + + DEF_HELP_URI = ( + "Installing msticpy", + "https://msticpy.readthedocs.io/en/latest/getting_started/Installing.html", + ) + + def __init__( + self, *args, help_uri: Union[Tuple[str, str], str, None] = None, **kwargs + ): + """ + Create import missing extra exception. + + Parameters + ---------- + help_uri : Union[Tuple[str, str], str, None], optional + Override the default help URI. + extra : str + The name of the setup extra that needs to be installed. + + """ + extra = kwargs.pop("extra", None) + if not extra: + raise AttributeError("Keyword argument 'extra' must be supplied") + mssg = "".join( + [ + "This feature requires one or more additional packages", + "to be installed.\n", + "To do this run the command:\n", + f"pip install msticpy[{extra}]", + ] + ) + add_args = [*args, mssg] + uri = help_uri or self.DEF_HELP_URI + super().__init__(*add_args, help_uri=uri, **kwargs) + + class MsticpyAzureConnectionError(MsticpyUserError): """Exception class for KqlConnection errors.""" diff --git a/msticpy/data/drivers/splunk_driver.py b/msticpy/data/drivers/splunk_driver.py index 150c2a80a..33bae9524 100644 --- a/msticpy/data/drivers/splunk_driver.py +++ b/msticpy/data/drivers/splunk_driver.py @@ -8,9 +8,6 @@ from typing import Any, Tuple, Union, Dict, Iterable, Optional import pandas as pd -import splunklib.client as sp_client -import splunklib.results as sp_results -from splunklib.client import AuthenticationError, HTTPError from .driver_base import DriverBase, QuerySource from ..._version import VERSION @@ -19,9 +16,21 @@ MsticpyConnectionError, MsticpyNotConnectedError, MsticpyUserConfigError, + MsticpyImportExtraError, ) from ...common.provider_settings import get_provider_settings, ProviderSettings +try: + import splunklib.client as sp_client + import splunklib.results as sp_results + from splunklib.client import AuthenticationError, HTTPError +except ImportError as imp_err: + raise MsticpyImportExtraError( + "Cannot use this feature without splunk-sdk installed", + title="Error importing splunk-sdk", + extra="splunk", + ) from imp_err + __version__ = VERSION __author__ = "Ashwin Patil" diff --git a/msticpy/sectools/vtlookupv3.py b/msticpy/sectools/vtlookupv3.py index 472d1ba65..7a4d8d2be 100644 --- a/msticpy/sectools/vtlookupv3.py +++ b/msticpy/sectools/vtlookupv3.py @@ -5,9 +5,18 @@ import pandas as pd from IPython.display import HTML, display -import vt -from vt_graph_api import VTGraph -from vt_graph_api import errors as vt_graph_errs +from ..common.exceptions import MsticpyImportExtraError + +try: + import vt + from vt_graph_api import VTGraph + from vt_graph_api import errors as vt_graph_errs +except ImportError as imp_err: + raise MsticpyImportExtraError( + "Cannot use this feature without vt-py and vt-graph-api packages installed.", + title="Error importing VirusTotal modules.", + extra="vt3", + ) from imp_err class MsticpyVTNoDataError(Exception): diff --git a/requirements.txt b/requirements.txt index 98e70b1be..dfa012f80 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,7 +27,6 @@ matplotlib>=3.0.0 msal~=1.0.0 msrest>=0.6.0 msrestazure>=0.6.0 -nest_asyncio>=1.4.0 networkx>=2.2 numpy>=1.15.4 pandas>=0.25.0 @@ -44,5 +43,3 @@ statsmodels>=0.11.1 tldextract>=2.2.2 tqdm>=4.36.1 urllib3>=1.23 -vt-graph-api>=1.0.1 -vt-py>=0.5.4 \ No newline at end of file diff --git a/setup.py b/setup.py index 184134dd1..10c2be118 100644 --- a/setup.py +++ b/setup.py @@ -9,53 +9,6 @@ import setuptools -INSTALL_REQUIRES = [ - "adal>=1.2.2", - "attrs>=18.2.0", - "azure-common>=1.1.18", - "azure-cli-core==2.5.0", - "azure-core>=1.2.2", - "azure-identity>=1.4.0", - "azure-keyvault-secrets>=4.0.0", - "azure-mgmt-compute>=4.6.2", - "azure-mgmt-keyvault>=2.0.0", - "azure-mgmt-monitor>=1.0.1", - "azure-mgmt-network>=2.7.0", - "azure-mgmt-resource>=2.2.0,<=10.1.0", - "azure-mgmt-subscription>=0.2.0", - "beautifulsoup4>=4.6.3", - "bokeh>=1.4.0", - "cryptography>=2.8", - "deprecated>=1.2.4", - "dnspython>=1.16.0", - "folium>=0.9.0", - "geoip2>=2.9.0", - "ipwhois>=1.1.0", - "ipython>=7.1.1", - "ipywidgets>=7.4.2", - "keyring>=13.2.1", - "Kqlmagic>=0.1.106", - "matplotlib>=3.0.0", - "msal~=1.0.0", - "msrest>=0.6.0", - "msrestazure>=0.6.0", - "networkx>=2.2", - "numpy>=1.15.4", - "pandas>=0.25.0", - "pytz>=2019.2", - "pyyaml>=3.13", - "requests>=2.21.1", - "scikit-learn>=0.20.2", - "scipy>=1.1.0", - "seaborn>=0.9.0", - "setuptools>=40.6.3", - "statsmodels>=0.11.1", - "tldextract>=2.2.2", - "tqdm>=4.36.1", - "urllib3>=1.23", -] - - with open("README.md", "r") as fh: LONG_DESC = fh.read() @@ -71,6 +24,13 @@ with open("requirements-dev.txt", "r") as fh: INSTALL_DEV_REQUIRES = fh.readlines() +# Extras definitions +EXTRAS = { + "dev": INSTALL_DEV_REQUIRES, + "vt3": ["vt-py>=0.5.4", "vt-graph-api>=1.0.1", "nest_asyncio>=1.4.0"], + "splunk": ["splunk-sdk>=1.6.0"], +} + setuptools.setup( name="msticpy", version=__version__, @@ -94,8 +54,17 @@ "Development Status :: 4 - Beta", ], install_requires=INSTALL_REQUIRES, - extras_require={"dev": INSTALL_DEV_REQUIRES}, - keywords=["security", "azure", "sentinel"], + extras_require=EXTRAS, + keywords=[ + "security", + "azure", + "sentinel", + "mstic", + "cybersec", + "infosec", + "cyber", + "cybersecurity", + ], zip_safe=False, include_package_data=True, )