mirror of https://github.com/MISP/PyMISP
				
				
				
			Merge branch 'template-cache' of https://github.com/mback2k/PyMISP into mback2k-template-cache
						commit
						6303c6c6a9
					
				|  | @ -31,6 +31,13 @@ | |||
|             ], | ||||
|             "version": "==4.8.0" | ||||
|         }, | ||||
|         "cachetools": { | ||||
|             "hashes": [ | ||||
|                 "sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae", | ||||
|                 "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a" | ||||
|             ], | ||||
|             "version": "==3.1.1" | ||||
|         }, | ||||
|         "certifi": { | ||||
|             "hashes": [ | ||||
|                 "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", | ||||
|  | @ -261,6 +268,13 @@ | |||
|             ], | ||||
|             "version": "==4.8.0" | ||||
|         }, | ||||
|         "cachetools": { | ||||
|             "hashes": [ | ||||
|                 "sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae", | ||||
|                 "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a" | ||||
|             ], | ||||
|             "version": "==3.1.1" | ||||
|         }, | ||||
|         "certifi": { | ||||
|             "hashes": [ | ||||
|                 "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", | ||||
|  |  | |||
|  | @ -4,9 +4,11 @@ | |||
| import sys | ||||
| import datetime | ||||
| import json | ||||
| import os | ||||
| from json import JSONEncoder | ||||
| import logging | ||||
| from enum import Enum | ||||
| import cachetools | ||||
| 
 | ||||
| from .exceptions import PyMISPInvalidFormat | ||||
| 
 | ||||
|  | @ -38,6 +40,12 @@ if sys.version_info < (3, 0): | |||
|             return timedelta(0) | ||||
| 
 | ||||
| 
 | ||||
| if (3, 0) <= sys.version_info < (3, 6): | ||||
|     OLD_PY3 = True | ||||
| else: | ||||
|     OLD_PY3 = False | ||||
| 
 | ||||
| 
 | ||||
| class Distribution(Enum): | ||||
|     your_organisation_only = 0 | ||||
|     this_community_only = 1 | ||||
|  | @ -80,7 +88,30 @@ class MISPEncode(JSONEncoder): | |||
|         return JSONEncoder.default(self, obj) | ||||
| 
 | ||||
| 
 | ||||
| class AbstractMISP(MutableMapping): | ||||
| class MISPFileCache(object): | ||||
|     # cache up to 150 JSON structures in class attribute | ||||
|     __file_cache = cachetools.LFUCache(150) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def _load_json(cls, path): | ||||
|         # use root class attribute as global cache | ||||
|         file_cache = cls.__file_cache | ||||
|         # use modified time with path as cache key | ||||
|         mtime = os.path.getmtime(path) | ||||
|         if path in file_cache: | ||||
|             ctime, data = file_cache[path] | ||||
|             if ctime == mtime: | ||||
|                 return data | ||||
|         with open(path, 'rb') as f: | ||||
|             if OLD_PY3: | ||||
|                 data = json.loads(f.read().decode()) | ||||
|             else: | ||||
|                 data = json.load(f) | ||||
|         file_cache[path] = (mtime, data) | ||||
|         return data | ||||
| 
 | ||||
| 
 | ||||
| class AbstractMISP(MutableMapping, MISPFileCache): | ||||
| 
 | ||||
|     def __init__(self, **kwargs): | ||||
|         """Abstract class for all the MISP objects""" | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ from deprecated import deprecated | |||
| from . import __version__, warning_2020 | ||||
| from .exceptions import PyMISPError, SearchError, NoURL, NoKey, PyMISPEmptyResponse | ||||
| from .mispevent import MISPEvent, MISPAttribute, MISPUser, MISPOrganisation, MISPSighting, MISPFeed, MISPObject, MISPSharingGroup | ||||
| from .abstract import AbstractMISP, MISPEncode | ||||
| from .abstract import AbstractMISP, MISPEncode, MISPFileCache | ||||
| 
 | ||||
| logger = logging.getLogger('pymisp') | ||||
| 
 | ||||
|  | @ -37,11 +37,6 @@ try: | |||
| except ImportError: | ||||
|     HAVE_REQUESTS = False | ||||
| 
 | ||||
| if (3, 0) <= sys.version_info < (3, 6): | ||||
|     OLD_PY3 = True | ||||
| else: | ||||
|     OLD_PY3 = False | ||||
| 
 | ||||
| try: | ||||
|     from requests_futures.sessions import FuturesSession | ||||
|     ASYNC_OK = True | ||||
|  | @ -58,7 +53,7 @@ Response (if any): | |||
| {}''' | ||||
| 
 | ||||
| 
 | ||||
| class PyMISP(object):  # pragma: no cover | ||||
| class PyMISP(MISPFileCache):  # pragma: no cover | ||||
|     """Python API for MISP | ||||
| 
 | ||||
|     :param url: URL of the MISP instance you want to connect to | ||||
|  | @ -140,11 +135,7 @@ class PyMISP(object):  # pragma: no cover | |||
| 
 | ||||
|     @deprecated(reason="Use ExpandedPyMISP.describe_types_local", version='2.4.110', action='default') | ||||
|     def get_local_describe_types(self): | ||||
|         with open(os.path.join(self.resources_path, 'describeTypes.json'), 'rb') as f: | ||||
|             if OLD_PY3: | ||||
|                 describe_types = json.loads(f.read().decode()) | ||||
|             else: | ||||
|                 describe_types = json.load(f) | ||||
|         describe_types = self._load_json(os.path.join(self.resources_path, 'describeTypes.json')) | ||||
|         return describe_types['result'] | ||||
| 
 | ||||
|     @deprecated(reason="Use ExpandedPyMISP.describe_types_remote", version='2.4.110', action='default') | ||||
|  |  | |||
|  | @ -106,8 +106,7 @@ class ExpandedPyMISP(PyMISP): | |||
|     @property | ||||
|     def describe_types_local(self): | ||||
|         '''Returns the content of describe types from the package''' | ||||
|         with (self.resources_path / 'describeTypes.json').open() as f: | ||||
|             describe_types = json.load(f) | ||||
|         describe_types = self._load_json(str(self.resources_path / 'describeTypes.json')) | ||||
|         return describe_types['result'] | ||||
| 
 | ||||
|     @property | ||||
|  |  | |||
|  | @ -111,11 +111,7 @@ class MISPAttribute(AbstractMISP): | |||
|         super(MISPAttribute, self).__init__() | ||||
|         if not describe_types: | ||||
|             ressources_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data') | ||||
|             with open(os.path.join(ressources_path, 'describeTypes.json'), 'rb') as f: | ||||
|                 if OLD_PY3: | ||||
|                     t = json.loads(f.read().decode()) | ||||
|                 else: | ||||
|                     t = json.load(f) | ||||
|             t = self._load_json(os.path.join(ressources_path, 'describeTypes.json')) | ||||
|             describe_types = t['result'] | ||||
|         self.__categories = describe_types['categories'] | ||||
|         self._types = describe_types['types'] | ||||
|  | @ -427,26 +423,14 @@ class MISPEvent(AbstractMISP): | |||
|         super(MISPEvent, self).__init__(**kwargs) | ||||
|         ressources_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data') | ||||
|         if strict_validation: | ||||
|             with open(os.path.join(ressources_path, 'schema.json'), 'rb') as f: | ||||
|                 if OLD_PY3: | ||||
|                     self.__json_schema = json.loads(f.read().decode()) | ||||
|                 else: | ||||
|                     self.__json_schema = json.load(f) | ||||
|             self.__json_schema = self._load_json(os.path.join(ressources_path, 'schema.json')) | ||||
|         else: | ||||
|             with open(os.path.join(ressources_path, 'schema-lax.json'), 'rb') as f: | ||||
|                 if OLD_PY3: | ||||
|                     self.__json_schema = json.loads(f.read().decode()) | ||||
|                 else: | ||||
|                     self.__json_schema = json.load(f) | ||||
|             self.__json_schema = self._load_json(os.path.join(ressources_path, 'schema-lax.json')) | ||||
|         if describe_types: | ||||
|             # This variable is used in add_attribute in order to avoid duplicating the structure | ||||
|             self._describe_types = describe_types | ||||
|         else: | ||||
|             with open(os.path.join(ressources_path, 'describeTypes.json'), 'rb') as f: | ||||
|                 if OLD_PY3: | ||||
|                     t = json.loads(f.read().decode()) | ||||
|                 else: | ||||
|                     t = json.load(f) | ||||
|             t = self._load_json(os.path.join(ressources_path, 'describeTypes.json')) | ||||
|             self._describe_types = t['result'] | ||||
| 
 | ||||
|         self._types = self._describe_types['types'] | ||||
|  | @ -1206,11 +1190,7 @@ class MISPObject(AbstractMISP): | |||
|     def _load_template_path(self, template_path): | ||||
|         if not os.path.exists(template_path): | ||||
|             return False | ||||
|         with open(template_path, 'rb') as f: | ||||
|             if OLD_PY3: | ||||
|                 self._definition = json.loads(f.read().decode()) | ||||
|             else: | ||||
|                 self._definition = json.load(f) | ||||
|         self._definition = self._load_json(template_path) | ||||
|         setattr(self, 'meta-category', self._definition['meta-category']) | ||||
|         self.template_uuid = self._definition['uuid'] | ||||
|         self.description = self._definition['description'] | ||||
|  |  | |||
							
								
								
									
										2
									
								
								setup.py
								
								
								
								
							
							
						
						
									
										2
									
								
								setup.py
								
								
								
								
							|  | @ -41,7 +41,7 @@ setup( | |||
|     ], | ||||
|     install_requires=['six', 'requests', 'python-dateutil', 'jsonschema', | ||||
|                       'python-dateutil', 'enum34;python_version<"3.4"', | ||||
|                       'functools32;python_version<"3.0"', 'deprecated'], | ||||
|                       'functools32;python_version<"3.0"', 'deprecated', 'cachetools'], | ||||
|     extras_require={'fileobjects': ['lief>=0.8,<0.10;python_version<"3.5"', 'lief>=0.10.0.dev0;python_version>"3.5"', 'python-magic', 'pydeep'], | ||||
|                     'neo': ['py2neo'], | ||||
|                     'openioc': ['beautifulsoup4'], | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Raphaël Vinot
						Raphaël Vinot