From 0a9da36bf4f2d6b2892131e40f1c55a89d003537 Mon Sep 17 00:00:00 2001
From: Alessandro Frigeri <alessandro.frigeri@inaf.it>
Date: Fri, 3 May 2019 14:15:22 +0200
Subject: [PATCH] Updated the classes with dataclass

---
 moondb/__pycache__/__init__.cpython-37.pyc | Bin 176 -> 0 bytes
 moondb/__pycache__/core.cpython-37.pyc     | Bin 6333 -> 0 bytes
 moondb/__pycache__/helpers.cpython-37.pyc  | Bin 3628 -> 0 bytes
 moondb/core.py                             | 230 ++++++++++++++++++---
 moondb/helpers.py                          | 122 +----------
 5 files changed, 200 insertions(+), 152 deletions(-)
 delete mode 100644 moondb/__pycache__/__init__.cpython-37.pyc
 delete mode 100644 moondb/__pycache__/core.cpython-37.pyc
 delete mode 100644 moondb/__pycache__/helpers.cpython-37.pyc

diff --git a/moondb/__pycache__/__init__.cpython-37.pyc b/moondb/__pycache__/__init__.cpython-37.pyc
deleted file mode 100644
index 754d9ddb58841c2a833c0254ae337d976d5d3058..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 176
zcmZ?b<>g{vU|{%v`*e&p0|Ucj5C?{t7#J8F7#J9eMHm<uQW#Pga~MJ(G-C)u3R5tH
zCi6>11_lOA##@Y9ews{CEXnyrsZs11sW}CyMa3%_ikKM~AjB_2{fzwFRQ<%9H2w6<
zlJcT#{esGpjQl*^-2D8!lq7v96(66Omst`YuUAlci^C>2KczG$)edAwF~~6-i~y`7
BD&+tG

diff --git a/moondb/__pycache__/core.cpython-37.pyc b/moondb/__pycache__/core.cpython-37.pyc
deleted file mode 100644
index 5db9fb7618733fefac79d26cdbf2585f954c4f1c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6333
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

diff --git a/moondb/__pycache__/helpers.cpython-37.pyc b/moondb/__pycache__/helpers.cpython-37.pyc
deleted file mode 100644
index 266ffa3ba729660dc43a256b5d69480c6458b973..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3628
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

diff --git a/moondb/core.py b/moondb/core.py
index a5a5a83..edc6285 100644
--- a/moondb/core.py
+++ b/moondb/core.py
@@ -5,46 +5,53 @@
 # MoonDB Python module
 # https://realpython.com/api-integration-in-python/
 
-import requests
+import sys
 import json 
 import urllib.parse
 import urllib3,socket
 import logging
-
+from dataclasses import dataclass
 from collections import namedtuple
 
+import requests
+#import attr
+
 class Mission:
    def __init__(self,name):
       self.name = name
    def __str__(self):
       return self.name
 
+@dataclass
 class Landmark:
-   def __init__(self,name):
-      self.name = name
+   """The Landmark class"""
+   name: str
+   GPNFID: int
+   GPNFURL: str
+   latitude: float
+   longitude: float
 
+   def asWkt(self):
+      point = "POINT ({} {})"
+      return point.format(self.longitude,self.latitude)
+
+@dataclass
 class Specimen:
-   def __init__(self):
-       self.specimenCode = ""
-       self.specimenName = ""
-       self.parentSpecimen = ""
-       self.childSpecimens = ""
-       self.specimenType = ""
-       self.samplingTechnique = ""
-       self.mission = ""
-       self.landmark = ""
-       self.lunarStation = ""
-       self.returnContainer = ""
-       self.weight = ""
-       self.pristinity = ""
-       self.pristinityDate = ""
-       self.description = ""
-   def say_hello(self):
-      print('Hello Moon!')
-   def __str__(self):
-      return self.specimenName
-   def __repr__(self):
-      return self.specimenName
+   specimenCode: str
+   specimenName: str
+   parentSpecimen: str
+   childSpecimens: list
+   specimenType: str
+   samplingTechnique: str
+   mission: str
+   landmark: str
+   lunarStation: str
+   returnContainer: str
+   weight: str
+   pristinity: str
+   pristinityDate: str
+   description: str
+
 
 class SpecimenType:
    def __init__(self,name):
@@ -92,9 +99,14 @@ class AnalyisMethod:
    def __init__(self,name):
       self.name = name
 
+class Analysis:
+   __slots__ = ('analysisCode','analyzedMaterial','comment','dataset','citation','dataResults')
+
+class DataResult:
+   __slots__ = ('unit', 'laboratory', 'variable', 'methodName', 'methodComment', 'value', 'methodCode')
 
 def _url(path):
-   print(urllib.parse.quote(path))
+   #print(urllib.parse.quote(path))
    return "http://api.moondb.org" + urllib.parse.quote(path)
 
 def _check_resp(resp):
@@ -115,13 +127,16 @@ def _get_resp(path):
       sys.exit(0)
    _check_resp(resp)
    r = resp.json()
+   #print(r)
    # To be checked with Peng
-   count = r['count']
-   if 'results' in r:
-      return count,r['results']
-   if 'result' in r:
-      return count,r['result']
-   
+   if 'result' and 'count' in r:
+      return r['count'],r['result']
+   if 'results' and 'count' in r:
+      return r['count'],r['results']
+   else:
+      return r
+
+
 
 def _json_object_hook(d): 
    return namedtuple('X', d.keys())(*d.values())
@@ -130,9 +145,158 @@ def json2obj(data):
    return json.loads(data, object_hook=_json_object_hook)
 
 
+def get_specimens(sc=None,mn=None,ln=None,sty=None,ste=None):
+   '''
+   Returns the specimen by specifying:
+   
+   Parameters
+   ----------
+   sc: list 
+       list of specimen codes
+   mn: list
+       list of mission names
+   ln: list
+       list of landmark names
+   sty: list
+       list of specimen types
+   ste: list
+       list of sampling techniques
+   '''
+   sp_list = []
+   if sc:
+      for s in sc: 
+         spec = _get_resp('/specimen/'+s) 
+         sp_list.append(spec)
+   if mn:
+      for n in mn:
+         spec = _get_resp('/specimenlist/mission/'+n) 
+         sp_list.append(spec)
+
+   if ln:
+      for n in ln:
+         spec = _get_resp('/specimenlist/mission/'+n) 
+         sp_list.append(spec)
+
+   if sty:
+      for st in sty:
+         spec = _get_resp('/specimenlist/mission/'+st) 
+         sp_list.append(spec)
+
+   if ste:
+      for st in ste:
+         spec = _get_resp('/specimenlist/mission/'+st) 
+         sp_list.append(spec)
+
+   sp_obj_list = []
+
+   for s in sp_list:
+      # dict unpack
+      s_o = Specimen(**s)
+      sp_obj_list.append(s_o)
+
+   return sp_obj_list
+
+
+def get_missions():
+   missions = []
+   resp = requests.get(_url('/authorities/missions/'))
+   _check_resp(resp)
+   for m_item in resp.json()['results']:
+      missions.append( Mission(m_item['name'] ))
+   return missions
+
+## Controlled Vocabularies
+
+def get_specimentypes():
+   st_list = []
+   count,st = _get_resp('/cv/specimentypes') 
+   for s in st:
+      stobj = SpecimenType(s['name'])
+      st_list.append(stobj)
+   return st_list
+
+def get_samplingtechniques():
+   st_list = []
+   count,st = _get_resp('/cv/samplingtechniques') 
+   for s in st:
+      stobj = SamplingTechnique(s['name'])
+      st_list.append(stobj)
+   return st_list
+
+def get_analyzedmaterials():
+   st_list = []
+   count,st = _get_resp('/cv/analyzedmaterials') 
+   for s in st:
+      stobj = AnalyzedMaterial(s['name'])
+      st_list.append(stobj)
+   return st_list
+
+def get_analytes():
+   analytes = []
+   count,an = _get_resp('/cv/analyzedmaterials') 
+   for a in an:
+      analytes.append( Analyte(m_item['name'] ))
+   return analytes
+
+def get_analysismethods():
+   am_list = []
+   count,am = _get_resp('/cv/analysismethods') 
+   for a in am:
+      aobj = AnalysisMethod(s['name'])
+      am_list.append(aobj)
+   return am_list
+
+def get_landmarks():
+   lm_list = []
+   count,lmlist = _get_resp('/authorities/landmarks') 
+   for l in lmlist:
+      lobj = Landmark(**l)
+      lm_list.append(lobj)
+   return lm_list
+
+def get_landmark( landmark_name ):
+   lms = get_landmarks()
+   for l in lms:
+      if l.name == landmark_name:
+         return l
+   return None
+
+def get_samplingtechnique():
+   pass
+
+
+
+class AnalysisFilter:
+   def __init__(self):
+      self.mission = []
+      self.landmark = []
+      self.specimenType = []
+      self.samplingTechnique = []
+      self.analyzedMaterial = []
+      self.analyte = []
+      self.analysisMethod = []
+   def _toJSON(self):
+      return json.dumps(self, default=lambda o: o.__dict__,sort_keys=True,separators=(",", ":"))
+
+   def get_results(self):
+      resp = requests.get(_url('/data/'+self._toJSON() ))
+      res_list = []
+      
+      for r in resp.json()['results']:
+         rd = dict(r)
+         analysis = namedtuple("Analysis", rd.keys())(*rd.values())
+         data_res_list = []
+         for r in analysis.dataResults:
+            data_res = namedtuple("dataResult", r.keys())(*r.values())
+            data_res_list.append(data_res)
+         analysis = analysis._replace(dataResults = data_res_list )
+         res_list.append(analysis) 
+      return res_list
+
+
 if __name__ == "__main__":
    m = get_missions()
-   f = Filter()
+   f = AnalysisFilter()
    f.specimenType = ["SOIL"]
    f.analyte = ["H2O","Ti"]
    f.mission = ["Apollo 11"]
diff --git a/moondb/helpers.py b/moondb/helpers.py
index ea3a2d8..68efea4 100644
--- a/moondb/helpers.py
+++ b/moondb/helpers.py
@@ -4,125 +4,9 @@
 # 
 # MoonDB Python module
 
-def get_specimen(sc=None,mn=None,ln=None,sty=None,ste=None):
-   '''
-   Get specimen by:
-   - specimen code - sc
-   - mission name - mn
-   - landmark name - ln
-   - speciment type - sty
-   - sampling technique - ste
-   '''
-   sp_list = []
-   if sc:
-      for s in sc: 
-         count,spec = _get_resp('/specimen/'+s) 
-         sp_list.extend(spec)
-   if mn:
-      for n in mn:
-         count,spec = _get_resp('/specimenlist/mission/'+n) 
-         sp_list.extend(spec)
+from .core import *
 
-   if ln:
-      for n in ln:
-         count,spec = _get_resp('/specimenlist/mission/'+n) 
-         sp_list.extend(spec)
+from collections import namedtuple
+import requests
 
-   if sty:
-      for st in sty:
-         count,spec = _get_resp('/specimenlist/mission/'+st) 
-         sp_list.extend(spec)
 
-   if ste:
-      for st in ste:
-         count,spec = _get_resp('/specimenlist/mission/'+st) 
-         sp_list.extend(spec)
-
-   from collections import namedtuple
-   
-   sp_obj_list = []
-
-   for s in sp_list:
-      s_obj = namedtuple("Specimen", s.keys())(*s.values())
-      sp_obj_list.append(s_obj)
-
-   return sp_obj_list
-
-
-def get_missions():
-   missions = []
-   resp = requests.get(_url('/authorities/missions/'))
-   _check_resp(resp)
-   for m_item in resp.json()['results']:
-      missions.append( Mission(m_item['name'] ))
-   return missions
-
-## Controlled Vocabularies
-
-def get_specimentypes():
-   st_list = []
-   count,st = _get_resp('/cv/specimentypes') 
-   for s in st:
-      stobj = SpecimenType(s['name'])
-      st_list.append(stobj)
-   return st_list
-
-def get_samplingtechniques():
-   st_list = []
-   count,st = _get_resp('/cv/samplingtechniques') 
-   for s in st:
-      stobj = SamplingTechnique(s['name'])
-      st_list.append(stobj)
-   return st_list
-
-def get_analyzedmaterials():
-   st_list = []
-   count,st = _get_resp('/cv/analyzedmaterials') 
-   for s in st:
-      stobj = AnalyzedMaterial(s['name'])
-      st_list.append(stobj)
-   return st_list
-
-def get_analytes():
-   analytes = []
-   count,an = _get_resp('/cv/analyzedmaterials') 
-   for a in an:
-      analytes.append( Analyte(m_item['name'] ))
-   return analytes
-
-def get_analysismethods():
-   am_list = []
-   count,am = _get_resp('/cv/analysismethods') 
-   for a in am:
-      aobj = AnalysisMethod(s['name'])
-      am_list.append(aobj)
-   return am_list
-
-def get_landmark():
-   pass
-
-def get_samplingtechnique():
-   pass
-
-
-
-class Filter:
-   def __init__(self):
-      self.mission = []
-      self.landmark = []
-      self.specimenType = []
-      self.samplingTechnique = []
-      self.analyzedMaterial = []
-      self.analyte = []
-      self.analysisMethod = []
-   def _toJSON(self):
-      return json.dumps(self, default=lambda o: o.__dict__,sort_keys=True,separators=(",", ":"))
-
-   def get_results(self):
-      resp = requests.get(_url('/data/'+self._toJSON() ))
-      res_list = []
-      
-      for r in resp.json()['results']:
-         rd = dict(r)
-         res_list.append(rd) 
-      return res_list
-- 
GitLab