Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions py2store/persisters/_arangodb_in_progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,19 @@ class ArangoDbPersister(Persister):

def __init__(
self,
user='root',
password='root',
url='http://127.0.0.1:8529',
db_name='py2store',
collection_name='test',
uri, # Example dict(
# user='root',
# password='root',
# url='http://127.0.0.1:8529',
# db_name='py2store',
# )
collection='test',
key_fields=('key',), # _id, _key and _rev are reserved by db
key_fields_separator='::',
):
self._connection = Connection(
arangoURL=url,
username=user,
password=password,
)

self._db_name = db_name
self._collection_name = collection_name
self._db_name = uri.pop('db_name')
self._connection = Connection(**uri)
self._collection_name = collection

# If DB not created:
if not self._connection.hasDatabase(self._db_name):
Expand Down
Empty file.
31 changes: 16 additions & 15 deletions py2store/persisters/couchdb_w_couchdb.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@

from py2store.base import Persister
from py2store.util import ModuleNotFoundErrorNiceMessage
from py2store.utils.uri_parsing import build_uri

with ModuleNotFoundErrorNiceMessage():
from couchdb import Server
from couchdb.client import DEFAULT_BASE_URL


class CouchDbPersister(Persister):
Expand Down Expand Up @@ -65,32 +68,30 @@ def clear(self):

def __init__(
self,
user='admin',
password='admin',
url='http://127.0.0.1:5984',
db_name='py2store',
uri=DEFAULT_BASE_URL,
collection='py2store',
key_fields=('_id',),
couchdb_client_kwargs=None
):
if couchdb_client_kwargs is None:
couchdb_client_kwargs = {}
if user and password:
# put credentials in url if provided like https://username:password@example.com:5984/
if '//' in url: # if scheme present
url = f'{url.split("//")[0]}//{user}:{password}@{url.split("//")[1]}'
else:
url = f'http//{user}:{password}@{url}'
self._couchdb_server = Server(url=url, **couchdb_client_kwargs)
self._db_name = db_name

self._couchdb_server = Server(url=uri, **couchdb_client_kwargs)
self._db_name = collection
# if db not created
if db_name not in self._couchdb_server:
self._couchdb_server.create(db_name)
self._cdb = self._couchdb_server[db_name]
if collection not in self._couchdb_server:
self._couchdb_server.create(collection)
self._cdb = self._couchdb_server[collection]
if isinstance(key_fields, str):
key_fields = (key_fields,)

self._key_fields = key_fields

@classmethod
def from_kwargs(cls, username, password, host='localhost', port=5984, scheme='http', database='', **kwargs):
uri = build_uri(scheme, database, username, password, host, port)
return cls(uri, **kwargs)

def __get_item_internal(self, k):
# some methods need original couch docs, so __getitem__ is divided on two methods
k = self.__replace_internals(k)
Expand Down
20 changes: 14 additions & 6 deletions py2store/persisters/dropbox_w_dropbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,27 @@ class DropboxPersister(Persister):
>>> del s['/py2store_data/test/_can_remove']
"""

def __init__(self, rootdir, oauth2_access_token,
connection_kwargs=None, files_upload_kwargs=None,
files_list_folder_kwargs=None, rev=None):

def __init__(
self,
uri='oauth2_access_token',
collection='my/root/dir',
connection_kwargs=None,
files_upload_kwargs=None,
files_list_folder_kwargs=None,
rev=None,
):
if connection_kwargs is None:
connection_kwargs = {}
if files_upload_kwargs is None:
files_upload_kwargs = {'mode': WriteMode.overwrite}
if files_list_folder_kwargs is None:
files_list_folder_kwargs = {'recursive': True, 'include_non_downloadable_files': False}

self._prefix = rootdir
self._con = Dropbox(oauth2_access_token, **connection_kwargs)
self._con = Dropbox(
uri, # OAuth token here
**connection_kwargs
)
self._prefix = collection # aka root dir
self._connection_kwargs = connection_kwargs
self._files_upload_kwargs = files_upload_kwargs
self._files_list_folder_kwargs = files_list_folder_kwargs
Expand Down
20 changes: 14 additions & 6 deletions py2store/persisters/dropbox_w_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@
class DropboxFolderCopyReader(Reader):
"""Makes a full local copy of the folder (by default, to a local temp folder) and gives access to it.
"""
def __init__(self, url, path=tempfile.gettempdir()):
self.url = url
self.path = path
def __init__(self, uri, collection=tempfile.gettempdir()):
self.url = uri
self.path = collection

os.makedirs(self.path, exist_ok=True)
self._zip_filepath = os.path.join(self.path, 'shared_folder.zip')

self._files = []
self._get_folder()

@classmethod
def from_kwargs(cls, **kwargs):
return cls(**kwargs)

def __getitem__(self, rel_path):
real_path = os.path.join(self.path, rel_path)
try:
Expand Down Expand Up @@ -51,13 +55,17 @@ def _unzip(self):


class DropboxFileCopyReader(Reader):
def __init__(self, url, path=None):
self.url = url
self.path = path or self._get_filename_from_url()
def __init__(self, uri, collection=None):
self.url = uri
self.path = collection or self._get_filename_from_url()

download_from_dropbox(self.url, self.path, as_zip=False)
self.file = open(self.path, 'r')

@classmethod
def from_kwargs(cls, **kwargs):
return cls(**kwargs)

def __getitem__(self, index):
self.file.seek(0)
return self.readlines()[index]
Expand Down
37 changes: 25 additions & 12 deletions py2store/persisters/ftp_persister.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from py2store.base import Persister
from ftplib import FTP, all_errors
import os.path
from io import BytesIO
from io import BytesIO

from py2store.utils.uri_parsing import build_uri, parse_uri


def remote_mkdir(ftp, remote_directory):
"""
Expand All @@ -16,7 +19,7 @@ def remote_mkdir(ftp, remote_directory):
# top-level relative directory must exist
return False
try:
ftp.cwd(remote_directory) # sub-directory exists
ftp.cwd(remote_directory) # sub-directory exists
except all_errors:
dirname, basename = os.path.split(remote_directory.rstrip('/'))
remote_mkdir(ftp, dirname) # make parent directories
Expand Down Expand Up @@ -58,19 +61,29 @@ class FtpPersister(Persister):
0
"""

def __init__(self,
user='dlpuser@dlptest.com',
password='fLDScD4Ynth0p4OJ6bW6qCxjh',
url='ftp.dlptest.com',
rootdir='./py2store',
encoding='utf8'
):
self._ftp = FTP(host=url, user=user, passwd=password)
self._rootdir = rootdir
def __init__(
self,
uri,
collection='./py2store',
encoding='utf8'
):
uri_parsed = parse_uri(uri)

self._ftp = FTP(
host=uri_parsed['hostname'],
user=uri_parsed['username'],
passwd=uri_parsed['password'],
)
self._rootdir = collection
self._encoding = encoding
self._ftp.encoding = encoding
remote_mkdir(self._ftp, self._rootdir)

@classmethod
def from_kwargs(cls, host, port=21, username='', password='', scheme='tcp', **kwargs):
uri = build_uri(scheme, username=username, password=password, host=host, port=port)
return cls(uri, **kwargs)

def __getitem__(self, k):
bio = BytesIO()
self._ftp.retrbinary("RETR {}".format(k), bio.write)
Expand Down Expand Up @@ -114,4 +127,4 @@ def __del__(self):
"""
Close ssh session when an object is deleted
"""
self._ftp.close()
self._ftp.close()
29 changes: 19 additions & 10 deletions py2store/persisters/mongo_w_pymongo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from py2store.base import Persister

from py2store.util import ModuleNotFoundErrorNiceMessage
from py2store.utils.uri_parsing import build_uri, parse_uri

with ModuleNotFoundErrorNiceMessage():
from pymongo import MongoClient
Expand Down Expand Up @@ -55,18 +56,20 @@ class MongoPersister(Persister):
{'first': 'Vitalik', 'last': 'Buterin'} --> {'yob': 1994, 'proj': 'ethereum', 'bdfl': True}
"""

def __init__(self, db_name='py2store', collection_name='test', key_fields=('_id',), data_fields=None,
mongo_client_kwargs=None):
if mongo_client_kwargs is None:
mongo_client_kwargs = {}
self._mongo_client = MongoClient(**mongo_client_kwargs)
self._db_name = db_name
self._collection_name = collection_name
self._mgc = self._mongo_client[db_name][collection_name]
def __init__(
self,
uri,
collection='test',
key_fields=('_id',),
data_fields=None,
):
uri, self._db_name = uri.rsplit('/', 1)
self._mongo_client = MongoClient(uri)
self._collection_name = collection
self._mgc = self._mongo_client[self._db_name][collection]

if isinstance(key_fields, str):
key_fields = (key_fields,)
if data_fields is None:
pass

self._key_projection = {k: True for k in key_fields}
if '_id' not in key_fields:
Expand All @@ -77,9 +80,15 @@ def __init__(self, db_name='py2store', collection_name='test', key_fields=('_id'
data_fields = {k: True for k in data_fields}
if '_id' not in data_fields:
data_fields['_id'] = False

self._data_fields = data_fields
self._key_fields = key_fields

@classmethod
def from_kwargs(cls, database, username, password, host='localhost', port=1433, scheme='mongodb', **kwargs):
uri = build_uri(scheme, database, username, password, host, port)
return cls(uri, **kwargs)

def __getitem__(self, k):
doc = self._mgc.find_one(k, projection=self._data_fields)
if doc is not None:
Expand Down
58 changes: 35 additions & 23 deletions py2store/persisters/sql_w_odbc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,41 @@
import subprocess
from collections.abc import MutableMapping

from py2store.util import ModuleNotFoundErrorNiceMessage
from py2store.utils.uri_parsing import parse_uri, build_uri

with ModuleNotFoundErrorNiceMessage():
import pyodbc

class SQLServerPersister(MutableMapping):
def __init__(self, conn_protocol='tcp', host='localhost', port='1433', db_username='SA', db_pass='Admin123x',
db_name='py2store', table_name='person', primary_key='id', data_fields=('name',)):

class SQLServerPersister(MutableMapping):
def __init__(self, uri, collection='py2store_default_table', primary_key='id', data_fields=('name',)):
"""
:param uri: Uniform Resource Identifier of a database you would like to use.
tcp://user:password@localhost:1433/my_db
or
user:password@localhost:1433/my_db
or even just
user:password/my_db

:param collection: name of the table to use, i.e. "my_table".
:param primary_key: primary key column name.
:param data_fields: data columns names.
"""
self.__check_dependencies()
self._sql_server_client = pyodbc.connect('DRIVER={{ODBC Driver 17 for SQL Server}};'
'SERVER={}:{},{};'
'DATABASE={};'
'UID={};'
'PWD={}'
.format(conn_protocol, host, port, db_name, db_username, db_pass))

uri_parsed = parse_uri(uri)
self._sql_server_client = pyodbc.connect(
'DRIVER={{ODBC Driver 17 for SQL Server}};'
'SERVER={scheme}:{hostname},{port};'
'DATABASE={database};'
'UID={username};'
'PWD={password}'
.format(**uri_parsed)
)

self._cursor = self._sql_server_client.cursor()
self._table_name = table_name
self._table_name = collection
self._primary_key = primary_key

self._select_all_query = "SELECT * from {table};".format(table=self._table_name)
Expand All @@ -26,18 +46,13 @@ def __init__(self, conn_protocol='tcp', host='localhost', port='1433', db_userna
self._del_query = "DELETE from {table} where {primary_key} = {{value}};".format(table=self._table_name,
primary_key=self._primary_key)

@classmethod
def from_kwargs(cls, database, username, password, host='localhost', port=1433, conn_protocol='tcp', **kwargs):
uri = build_uri(conn_protocol, database, username, password, host, port)
return cls(uri, **kwargs)

@staticmethod
def __check_dependencies():
import pkg_resources
installed_packages = [pkg.project_name for pkg in pkg_resources.working_set]
if 'pyodbc' not in installed_packages:
raise ModuleNotFoundError("'SQLServerPersister' depends on the module 'pyodbc' which is not installed. "
"Try installing dependency using 'pip install pyodbc'.")

# import pyodbc globally
global pyodbc
import pyodbc

if 'ubuntu' in platform.platform().lower():
result = subprocess.Popen(["dpkg", "-s", "msodbcsql17"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = result.communicate()
Expand Down Expand Up @@ -115,6 +130,3 @@ def test_sqlserver_persister():

print("Getting the length")
print(len(sql_server_persister))


test_sqlserver_persister()
Loading