From 1e77a7f7b3d2463cdf780f2e2f0527566d32fe0c Mon Sep 17 00:00:00 2001
From: Alessandro Frigeri <alessandro.frigeri@inaf.it>
Date: Fri, 3 May 2019 08:23:14 +0200
Subject: [PATCH] Scaffolding the module

---
 MANIFEST.in                                |   2 +
 README.md                                  |   8 ++
 example1.ipynb => examples/example1.ipynb  |   0
 moondb/__init__.py                         |   2 +
 moondb/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 176 bytes
 moondb/__pycache__/core.cpython-37.pyc     | Bin 0 -> 6333 bytes
 moondb/__pycache__/helpers.cpython-37.pyc  | Bin 0 -> 3628 bytes
 moondb.py => moondb/core.py                | 130 ---------------------
 moondb/helpers.py                          | 128 ++++++++++++++++++++
 setup.py                                   |  21 ++++
 tests/__init__.py                          |   0
 tests/context.py                           |   5 +
 tests/test_moondb.py                       |   8 ++
 13 files changed, 174 insertions(+), 130 deletions(-)
 create mode 100644 MANIFEST.in
 rename example1.ipynb => examples/example1.ipynb (100%)
 create mode 100644 moondb/__init__.py
 create mode 100644 moondb/__pycache__/__init__.cpython-37.pyc
 create mode 100644 moondb/__pycache__/core.cpython-37.pyc
 create mode 100644 moondb/__pycache__/helpers.cpython-37.pyc
 rename moondb.py => moondb/core.py (56%)
 mode change 100755 => 100644
 create mode 100644 moondb/helpers.py
 create mode 100644 setup.py
 create mode 100644 tests/__init__.py
 create mode 100644 tests/context.py
 create mode 100644 tests/test_moondb.py

diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..93cc7e9
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,2 @@
+include README.md
+include examples/*
diff --git a/README.md b/README.md
index 09fecd3..6cfc524 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,14 @@ MoonDB is a NASA-funded quality-controlled data system that will preserve, digit
 
 PyMoonDB is a python client to the Application Program Interface made available by the MoonDB project.
 
+# Installation
 
+Within the directory where setup.py is placed, type:
 
+pip install -e .
 
+
+To use (with caution), simply do::
+
+    >>> import funniest
+    >>> print funniest.joke()
diff --git a/example1.ipynb b/examples/example1.ipynb
similarity index 100%
rename from example1.ipynb
rename to examples/example1.ipynb
diff --git a/moondb/__init__.py b/moondb/__init__.py
new file mode 100644
index 0000000..c445064
--- /dev/null
+++ b/moondb/__init__.py
@@ -0,0 +1,2 @@
+from .core import *
+from .helpers import *
diff --git a/moondb/__pycache__/__init__.cpython-37.pyc b/moondb/__pycache__/__init__.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..754d9ddb58841c2a833c0254ae337d976d5d3058
GIT binary patch
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

literal 0
HcmV?d00001

diff --git a/moondb/__pycache__/core.cpython-37.pyc b/moondb/__pycache__/core.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5db9fb7618733fefac79d26cdbf2585f954c4f1c
GIT binary patch
literal 6333
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

literal 0
HcmV?d00001

diff --git a/moondb/__pycache__/helpers.cpython-37.pyc b/moondb/__pycache__/helpers.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..266ffa3ba729660dc43a256b5d69480c6458b973
GIT binary patch
literal 3628
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

literal 0
HcmV?d00001

diff --git a/moondb.py b/moondb/core.py
old mode 100755
new mode 100644
similarity index 56%
rename from moondb.py
rename to moondb/core.py
index a1b7aff..a5a5a83
--- a/moondb.py
+++ b/moondb/core.py
@@ -88,13 +88,11 @@ class AnalysisMethod:
       return self.name
 
 
-
 class AnalyisMethod:
    def __init__(self,name):
       self.name = name
 
 
-
 def _url(path):
    print(urllib.parse.quote(path))
    return "http://api.moondb.org" + urllib.parse.quote(path)
@@ -125,55 +123,6 @@ def _get_resp(path):
       return count,r['result']
    
 
-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)
-
-   if ln:
-      for n in ln:
-         count,spec = _get_resp('/specimenlist/mission/'+n) 
-         sp_list.extend(spec)
-
-   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 _json_object_hook(d): 
    return namedtuple('X', d.keys())(*d.values())
 
@@ -181,85 +130,6 @@ def json2obj(data):
    return json.loads(data, object_hook=_json_object_hook)
 
 
-
-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
-
-
 if __name__ == "__main__":
    m = get_missions()
    f = Filter()
diff --git a/moondb/helpers.py b/moondb/helpers.py
new file mode 100644
index 0000000..ea3a2d8
--- /dev/null
+++ b/moondb/helpers.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python3
+# 
+# (c) 2019 Alessandro Frigeri, Istituto Nazionale di Astrofisica
+# 
+# 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)
+
+   if ln:
+      for n in ln:
+         count,spec = _get_resp('/specimenlist/mission/'+n) 
+         sp_list.extend(spec)
+
+   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
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..3e6292c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+from setuptools import setup
+
+def readme():
+    with open('README.md') as f:
+        return f.read()
+
+
+setup(name='moondb',
+      version='0.1',
+      description='Accessing the MoonDB lunar sample database',
+      url='https://www.ict.inaf.it/gitlab/alessandro.frigeri/python-moondb',
+      author='Alessandro Frigeri',
+      author_email='Alessandro.Frigeri@inaf.it',
+      license='MIT',
+      packages=['moondb'],
+      install_requires=[
+          'markdown',
+          'requests',
+          'urllib3'
+      ],
+      zip_safe=False)
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/context.py b/tests/context.py
new file mode 100644
index 0000000..ec28a17
--- /dev/null
+++ b/tests/context.py
@@ -0,0 +1,5 @@
+import os
+import sys
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+import sample
diff --git a/tests/test_moondb.py b/tests/test_moondb.py
new file mode 100644
index 0000000..7fadc53
--- /dev/null
+++ b/tests/test_moondb.py
@@ -0,0 +1,8 @@
+from unittest import TestCase
+
+import moondb
+
+class TestMoonDB(TestCase):
+    def test_is_string(self):
+        s = funniest.joke()
+        self.assertTrue(isinstance(s, basestring))
-- 
GitLab