mirror of
https://github.com/bellingcat/snscrape.git
synced 2026-06-12 20:38:29 +03:00
Include properties in JSON representation
This fixes the lack of the profile URL on Twitter users because it's generated using the username rather than set explicitly as a field.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import abc
|
import abc
|
||||||
|
import copy
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import datetime
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
@@ -19,6 +20,8 @@ class _DeprecatedProperty:
|
|||||||
self.replStr = replStr
|
self.replStr = replStr
|
||||||
|
|
||||||
def __get__(self, obj, objType):
|
def __get__(self, obj, objType):
|
||||||
|
if obj is None: # if the access is through the class using _DeprecatedProperty rather than an instance of the class:
|
||||||
|
return self
|
||||||
warnings.warn(f'{self.name} is deprecated, use {self.replStr} instead', FutureWarning, stacklevel = 2)
|
warnings.warn(f'{self.name} is deprecated, use {self.replStr} instead', FutureWarning, stacklevel = 2)
|
||||||
return self.repl(obj)
|
return self.repl(obj)
|
||||||
|
|
||||||
@@ -30,17 +33,35 @@ def _json_serialise_datetime(obj):
|
|||||||
raise TypeError(f'Object of type {type(obj)} is not JSON serializable')
|
raise TypeError(f'Object of type {type(obj)} is not JSON serializable')
|
||||||
|
|
||||||
|
|
||||||
|
def _json_dataclass_to_dict(obj):
|
||||||
|
if isinstance(obj, _JSONDataclass) or dataclasses.is_dataclass(obj):
|
||||||
|
out = {}
|
||||||
|
for field in dataclasses.fields(obj):
|
||||||
|
out[field.name] = _json_dataclass_to_dict(getattr(obj, field.name))
|
||||||
|
# Add in (non-deprecated) properties
|
||||||
|
for k in dir(obj):
|
||||||
|
if isinstance(getattr(type(obj), k, None), property):
|
||||||
|
out[k] = _json_dataclass_to_dict(getattr(obj, k))
|
||||||
|
return out
|
||||||
|
elif isinstance(obj, (tuple, list)):
|
||||||
|
return type(obj)(_json_dataclass_to_dict(x) for x in obj)
|
||||||
|
elif isinstance(obj, dict):
|
||||||
|
return {_json_dataclass_to_dict(k): _json_dataclass_to_dict(v) for k, v in obj.items()}
|
||||||
|
elif isinstance(obj, set):
|
||||||
|
return {_json_dataclass_to_dict(v) for v in obj}
|
||||||
|
else:
|
||||||
|
return copy.deepcopy(obj)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class _JSONDataclass:
|
class _JSONDataclass:
|
||||||
'''A base class for dataclasses for conversion to JSON'''
|
'''A base class for dataclasses for conversion to JSON'''
|
||||||
|
|
||||||
def json(self):
|
def json(self):
|
||||||
'''Convert the object to a JSON string'''
|
'''Convert the object to a JSON string'''
|
||||||
out = dataclasses.asdict(self)
|
out = _json_dataclass_to_dict(self)
|
||||||
for key, value in list(out.items()): # Modifying the dict below, so make a copy first
|
for key, value in list(out.items()): # Modifying the dict below, so make a copy first
|
||||||
if isinstance(value, _JSONDataclass):
|
if isinstance(value, IntWithGranularity):
|
||||||
out[key] = value.json()
|
|
||||||
elif isinstance(value, IntWithGranularity):
|
|
||||||
out[key] = int(value)
|
out[key] = int(value)
|
||||||
assert f'{key}.granularity' not in out, f'Granularity collision on {key}.granularity'
|
assert f'{key}.granularity' not in out, f'Granularity collision on {key}.granularity'
|
||||||
out[f'{key}.granularity'] = value.granularity
|
out[f'{key}.granularity'] = value.granularity
|
||||||
|
|||||||
Reference in New Issue
Block a user