rda-python-dsquasar 2.0.11__tar.gz → 3.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. rda_python_dsquasar-3.0.1/PKG-INFO +87 -0
  2. rda_python_dsquasar-3.0.1/README.md +70 -0
  3. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/pyproject.toml +1 -1
  4. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar/ds_quasar.py +2 -2
  5. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar/dsquasar.py +2 -2
  6. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar/dstacc.py +2 -2
  7. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar/taccrec.py +97 -64
  8. rda_python_dsquasar-3.0.1/src/rda_python_dsquasar.egg-info/PKG-INFO +87 -0
  9. rda_python_dsquasar-2.0.11/PKG-INFO +0 -18
  10. rda_python_dsquasar-2.0.11/README.md +0 -1
  11. rda_python_dsquasar-2.0.11/src/rda_python_dsquasar.egg-info/PKG-INFO +0 -18
  12. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/LICENSE +0 -0
  13. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/setup.cfg +0 -0
  14. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar/__init__.py +0 -0
  15. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar/tacctar.py +0 -0
  16. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar.egg-info/SOURCES.txt +0 -0
  17. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar.egg-info/dependency_links.txt +0 -0
  18. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar.egg-info/entry_points.txt +0 -0
  19. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar.egg-info/requires.txt +0 -0
  20. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/src/rda_python_dsquasar.egg-info/top_level.txt +0 -0
  21. {rda_python_dsquasar-2.0.11 → rda_python_dsquasar-3.0.1}/test/test_dsquasar.py +0 -0
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: rda_python_dsquasar
3
+ Version: 3.0.1
4
+ Summary: RDA Python package to backup and recover RDA data archives to and from GLOBUS Quasar backup server
5
+ Author-email: Zaihua Ji <zji@ucar.edu>
6
+ Project-URL: Homepage, https://github.com/NCAR/rda-python-dsquasar
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Requires-Python: >=3.7
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: rda_python_common
15
+ Requires-Dist: rda_python_dsarch
16
+ Dynamic: license-file
17
+
18
+ # rda_python_dsquasar
19
+
20
+ RDA Python package to back up and recover RDA data archives to and from the
21
+ GLOBUS Quasar backup server.
22
+
23
+ ## Programs
24
+
25
+ The package installs the following command-line utilities, all running as the
26
+ current user:
27
+
28
+ - `dsquasar` — back up and restore RDA dataset archives via Quasar
29
+ - `tacctar` — create tar bundles for Quasar archival
30
+ - `taccrec` — recover content from Quasar tar bundles
31
+
32
+ Run any program with `--help` (or `-h`) for full usage details.
33
+
34
+ ## Environment setup
35
+
36
+ Create a Python environment first; package installs in the next section run
37
+ inside whichever environment you activate here.
38
+
39
+ ### Option A — Python venv (DECS machines)
40
+
41
+ ```bash
42
+ python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
43
+ source $ENVHOME/bin/activate
44
+ ```
45
+
46
+ ### Option B — Conda (DAV/Casper)
47
+
48
+ ```bash
49
+ conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
50
+ conda activate $ENVHOME
51
+ ```
52
+
53
+ ## Installing rda-python-dsquasar
54
+
55
+ Pick whichever install mode fits your workflow. All variants pull in the
56
+ transitive dependencies (`rda_python_common`, `rda_python_dsarch`)
57
+ automatically.
58
+
59
+ For local development, clone this repo alongside your project and install it
60
+ in editable mode so that changes are picked up without re-installing:
61
+
62
+ ```bash
63
+ git clone https://github.com/NCAR/rda-python-dsquasar.git
64
+ cd rda-python-dsquasar
65
+ pip install -e .
66
+ ```
67
+
68
+ To test a specific branch (e.g. an in-progress feature or fix branch), pass
69
+ `-b/--branch` to `git clone`:
70
+
71
+ ```bash
72
+ git clone -b <branch-name> https://github.com/NCAR/rda-python-dsquasar.git
73
+ cd rda-python-dsquasar
74
+ pip install -e .
75
+ ```
76
+
77
+ For a regular (non-editable) install from a checkout:
78
+
79
+ ```bash
80
+ pip install /path/to/rda-python-dsquasar
81
+ ```
82
+
83
+ For a production install on a system that uses the published distribution:
84
+
85
+ ```bash
86
+ pip install rda_python_dsquasar
87
+ ```
@@ -0,0 +1,70 @@
1
+ # rda_python_dsquasar
2
+
3
+ RDA Python package to back up and recover RDA data archives to and from the
4
+ GLOBUS Quasar backup server.
5
+
6
+ ## Programs
7
+
8
+ The package installs the following command-line utilities, all running as the
9
+ current user:
10
+
11
+ - `dsquasar` — back up and restore RDA dataset archives via Quasar
12
+ - `tacctar` — create tar bundles for Quasar archival
13
+ - `taccrec` — recover content from Quasar tar bundles
14
+
15
+ Run any program with `--help` (or `-h`) for full usage details.
16
+
17
+ ## Environment setup
18
+
19
+ Create a Python environment first; package installs in the next section run
20
+ inside whichever environment you activate here.
21
+
22
+ ### Option A — Python venv (DECS machines)
23
+
24
+ ```bash
25
+ python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
26
+ source $ENVHOME/bin/activate
27
+ ```
28
+
29
+ ### Option B — Conda (DAV/Casper)
30
+
31
+ ```bash
32
+ conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
33
+ conda activate $ENVHOME
34
+ ```
35
+
36
+ ## Installing rda-python-dsquasar
37
+
38
+ Pick whichever install mode fits your workflow. All variants pull in the
39
+ transitive dependencies (`rda_python_common`, `rda_python_dsarch`)
40
+ automatically.
41
+
42
+ For local development, clone this repo alongside your project and install it
43
+ in editable mode so that changes are picked up without re-installing:
44
+
45
+ ```bash
46
+ git clone https://github.com/NCAR/rda-python-dsquasar.git
47
+ cd rda-python-dsquasar
48
+ pip install -e .
49
+ ```
50
+
51
+ To test a specific branch (e.g. an in-progress feature or fix branch), pass
52
+ `-b/--branch` to `git clone`:
53
+
54
+ ```bash
55
+ git clone -b <branch-name> https://github.com/NCAR/rda-python-dsquasar.git
56
+ cd rda-python-dsquasar
57
+ pip install -e .
58
+ ```
59
+
60
+ For a regular (non-editable) install from a checkout:
61
+
62
+ ```bash
63
+ pip install /path/to/rda-python-dsquasar
64
+ ```
65
+
66
+ For a production install on a system that uses the published distribution:
67
+
68
+ ```bash
69
+ pip install rda_python_dsquasar
70
+ ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rda_python_dsquasar"
7
- version = "2.0.11"
7
+ version = "3.0.1"
8
8
  authors = [
9
9
  { name="Zaihua Ji", email="zji@ucar.edu" },
10
10
  ]
@@ -91,7 +91,7 @@ TFCOUNT = 100 # if file count is greater, use MINSIZE for tar file
91
91
  SUBLMTS = 2000 # file count limit for a sub-group
92
92
 
93
93
  PGBACK = {
94
- 'workdir' : "{}/{}/quasar_backup".format(PgLOG.PGLOG['GDEXWORK'], PgLOG.PGLOG['GDEXUSER']),
94
+ 'workdir' : "{}/{}/quasar_backup".format(PgLOG.PGLOG['GDEXWORK'], PgLOG.PGLOG['COMMONUSER']),
95
95
  'mproc' : 1,
96
96
  'action' : CTACTS,
97
97
  'chgdays' : 0,
@@ -1092,7 +1092,7 @@ def evaluate_file_stat(dsid, cate, pgrec):
1092
1092
  chome = PgLOG.PGLOG['DECSHOME'] if cate == 's' else PgLOG.PGLOG['DSDHOME']
1093
1093
 
1094
1094
  if pgrec['locflag'] == 'O':
1095
- bucket = 'gdex-decsdata' if cate == 's' else PgLOG.PGLOC['OBJCTBKT']
1095
+ bucket = 'gdex-decsdata' if cate == 's' else PgLOG.PGLOG['OBJCTBKT']
1096
1096
  ofile = PgLOG.join_paths(dsid, fname)
1097
1097
  info = PgFile.check_object_file(ofile, bucket, 1, ERRACT)
1098
1098
  if not info: return False
@@ -85,7 +85,7 @@ class DsQuasar(PgCMD, PgSplit):
85
85
  self.TFCOUNT = 100 # if file count is greater, use self.MINSIZE for tar file
86
86
  self.SUBLMTS = 2000 # file count limit for a sub-group
87
87
  self.PGBACK = {
88
- 'workdir' : "{}/{}/quasar_backup".format(self.PGLOG['GDEXWORK'], self.PGLOG['GDEXUSER']),
88
+ 'workdir' : "{}/{}/quasar_backup".format(self.PGLOG['GDEXWORK'], self.PGLOG['COMMONUSER']),
89
89
  'mproc' : 1,
90
90
  'action' : self.CTACTS,
91
91
  'chgdays' : 0,
@@ -920,7 +920,7 @@ class DsQuasar(PgCMD, PgSplit):
920
920
  fname = pgrec[tname]
921
921
  chome = self.PGLOG['DECSHOME'] if cate == 's' else self.PGLOG['DSDHOME']
922
922
  if pgrec['locflag'] == 'O':
923
- bucket = 'gdex-decsdata' if cate == 's' else self.PGLOC['OBJCTBKT']
923
+ bucket = 'gdex-decsdata' if cate == 's' else self.PGLOG['OBJCTBKT']
924
924
  ofile = self.join_paths(dsid, fname)
925
925
  info = self.check_object_file(ofile, bucket, 1, self.ERRACT)
926
926
  if not info: return False
@@ -81,7 +81,7 @@ class DsTACC(PgCMD, PgSplit):
81
81
  self.ONESIZE = 20*self.PGLOG['ONEGBS'] # 20GB, minimal file size to tar a single file
82
82
  self.TFCOUNT = 1000000 # if file count is greater, use self.MINSIZE for tar file
83
83
  self.PGBACK = {
84
- 'workdir' : "{}/{}/tacc_backup".format(self.PGLOG['GDEXWORK'], self.PGLOG['GDEXUSER']),
84
+ 'workdir' : "{}/{}/tacc_backup".format(self.PGLOG['GDEXWORK'], self.PGLOG['COMMONUSER']),
85
85
  'mproc' : 1,
86
86
  'action' : self.CTACTS,
87
87
  'chgdays' : 0,
@@ -857,7 +857,7 @@ class DsTACC(PgCMD, PgSplit):
857
857
  fname = pgrec[tname]
858
858
  chome = self.PGLOG['DECSHOME'] if cate == 's' else self.PGLOG['DSDHOME']
859
859
  if pgrec['locflag'] == 'O':
860
- bucket = 'gdex-decsdata' if cate == 's' else self.PGLOC['OBJCTBKT']
860
+ bucket = 'gdex-decsdata' if cate == 's' else self.PGLOG['OBJCTBKT']
861
861
  ofile = self.join_paths(dsid, fname)
862
862
  info = self.check_object_file(ofile, bucket, 1, self.ERRACT)
863
863
  if not info: return False
@@ -5,6 +5,8 @@ import argparse
5
5
  import psycopg2
6
6
  import hashlib
7
7
  from datetime import datetime
8
+ import time
9
+ from psycopg2 import OperationalError
8
10
 
9
11
  def get_tar_summary_and_details(member_list_path):
10
12
  details = []
@@ -17,7 +19,7 @@ def get_tar_summary_and_details(member_list_path):
17
19
  with open(member_list_path, 'r') as f:
18
20
  for idx, line in enumerate(f):
19
21
  line = line.strip()
20
- if not line or line.startswith('-rw') is False:
22
+ if not line:
21
23
  continue
22
24
  parts = line.split()
23
25
  if len(parts) < 6:
@@ -68,60 +70,82 @@ def get_tar_summary_and_details(member_list_path):
68
70
  'dsid': dsid
69
71
  }, member_details
70
72
 
73
+ def connect_with_retry(db_params, max_retries=1, delay=2):
74
+ attempt = 0
75
+ while attempt <= max_retries:
76
+ try:
77
+ return psycopg2.connect(**db_params)
78
+ except OperationalError as e:
79
+ if 'server closed the connection unexpectedly' in str(e) and attempt < max_retries:
80
+ time.sleep(delay)
81
+ attempt += 1
82
+ continue
83
+ raise
84
+
71
85
  def insert_tfile_row(summary, db_params, extra, update_on_conflict=False, member_details=None):
72
86
  table_name = 'dssdb.tfile'
73
- conn = psycopg2.connect(**db_params)
74
- cur = conn.cursor()
75
- columns = [
76
- 'tfile', 'data_size', 'wcount', 'date_created', 'time_created',
77
- 'date_modified', 'time_modified', 'file_format', 'status',
78
- 'uid', 'dsid', 'data_format', 'disp_order', 'dsids', 'note'
79
- ]
80
- values = [
81
- summary['tfile'], summary['data_size'], summary['wcount'],
82
- summary['date_created'], summary['time_created'],
83
- summary['date_modified'], summary['time_modified'],
84
- 'tar', 'T',
85
- extra.get('uid'), extra.get('dsid'), extra.get('data_format'),
86
- extra.get('disp_order'), extra.get('dsids'), extra.get('note')
87
- ]
88
- placeholders = ','.join(['%s'] * len(columns))
89
- sql = f"INSERT INTO {table_name} ({', '.join(columns)}) VALUES ({placeholders})"
90
- if update_on_conflict:
91
- update_cols = [col for col in columns if col != 'tfile']
92
- set_clause = ', '.join([f"{col}=EXCLUDED.{col}" for col in update_cols])
93
- sql += f" ON CONFLICT (tfile) DO UPDATE SET {set_clause}"
94
- try:
95
- cur.execute(sql, values)
96
- conn.commit()
97
- # Retrieve tid for the just-inserted tfile row
98
- cur.execute(f"SELECT tid FROM {table_name} WHERE tfile=%s", (summary['tfile'],))
99
- row = cur.fetchone()
100
- tid = row[0] if row else None
101
- # Update wfile tables if member_details provided
102
- if member_details and tid is not None:
103
- for m in member_details:
104
- name = m['name']
105
- if '/' in name:
106
- cdsid, wfile = name.split('/', 1)
107
- else:
108
- cdsid, wfile = name, ''
109
- wfile_table = f"dssdb.wfile_{cdsid}"
110
- # Check if table exists
111
- cur.execute("SELECT to_regclass(%s)", (wfile_table,))
112
- exists = cur.fetchone()[0]
113
- if not exists:
114
- continue
115
- # Update tid if record exists
116
- cur.execute(f"UPDATE {wfile_table} SET tid=%s WHERE wfile=%s", (tid, wfile))
117
- conn.commit()
118
- except Exception as e:
119
- print(f"Database error: {e}")
120
- conn.rollback()
121
- raise
122
- finally:
123
- cur.close()
124
- conn.close()
87
+ attempt = 0
88
+ max_retries = 1
89
+ while attempt <= max_retries:
90
+ try:
91
+ conn = connect_with_retry(db_params)
92
+ cur = conn.cursor()
93
+ columns = [
94
+ 'tfile', 'data_size', 'wcount', 'date_created', 'time_created',
95
+ 'date_modified', 'time_modified', 'file_format', 'status',
96
+ 'uid', 'dsid', 'data_format', 'disp_order', 'dsids', 'note'
97
+ ]
98
+ values = [
99
+ summary['tfile'], summary['data_size'], summary['wcount'],
100
+ summary['date_created'], summary['time_created'],
101
+ summary['date_modified'], summary['time_modified'],
102
+ 'tar', 'T',
103
+ extra.get('uid'), extra.get('dsid'), extra.get('data_format'),
104
+ extra.get('disp_order'), extra.get('dsids'), extra.get('note')
105
+ ]
106
+ placeholders = ','.join(['%s'] * len(columns))
107
+ sql = f"INSERT INTO {table_name} ({', '.join(columns)}) VALUES ({placeholders})"
108
+ if update_on_conflict:
109
+ update_cols = [col for col in columns if col != 'tfile']
110
+ set_clause = ', '.join([f"{col}=EXCLUDED.{col}" for col in update_cols])
111
+ sql += f" ON CONFLICT (tfile) DO UPDATE SET {set_clause}"
112
+ cur.execute(sql, values)
113
+ conn.commit()
114
+ cur.execute(f"SELECT tid FROM {table_name} WHERE tfile=%s", (summary['tfile'],))
115
+ row = cur.fetchone()
116
+ tid = row[0] if row else None
117
+ if member_details and tid is not None:
118
+ for m in member_details:
119
+ name = m['name']
120
+ if '/' in name:
121
+ cdsid, wfile = name.split('/', 1)
122
+ else:
123
+ cdsid, wfile = name, ''
124
+ wfile_table = f"dssdb.wfile_{cdsid}"
125
+ cur.execute("SELECT to_regclass(%s)", (wfile_table,))
126
+ exists = cur.fetchone()[0]
127
+ if not exists:
128
+ continue
129
+ cur.execute(f"UPDATE {wfile_table} SET tid=%s WHERE wfile=%s", (tid, wfile))
130
+ conn.commit()
131
+ cur.close()
132
+ conn.close()
133
+ break
134
+ except Exception as e:
135
+ if 'server closed the connection unexpectedly' in str(e) and attempt < max_retries:
136
+ attempt += 1
137
+ time.sleep(2)
138
+ continue
139
+ print(f"Database error: {e}")
140
+ try:
141
+ cur.close()
142
+ except:
143
+ pass
144
+ try:
145
+ conn.close()
146
+ except:
147
+ pass
148
+ raise
125
149
 
126
150
  def get_uid_from_logname(db_params):
127
151
  import getpass
@@ -130,17 +154,26 @@ def get_uid_from_logname(db_params):
130
154
  logname = os.getlogin()
131
155
  except Exception:
132
156
  logname = os.environ.get('USER') or getpass.getuser()
133
- conn = psycopg2.connect(**db_params)
134
- cur = conn.cursor()
135
- # Ensure logname is quoted as a string in the query
136
- cur.execute("SELECT userno FROM dssdb.dssgrp WHERE logname=%s LIMIT 1", (str(logname),))
137
- row = cur.fetchone()
138
- cur.close()
139
- conn.close()
140
- if row:
141
- return row[0]
142
- else:
143
- raise ValueError(f"User logname '{logname}' not found in dssdb.dssgrp table.")
157
+ attempt = 0
158
+ max_retries = 1
159
+ while attempt <= max_retries:
160
+ try:
161
+ conn = connect_with_retry(db_params)
162
+ cur = conn.cursor()
163
+ cur.execute("SELECT userno FROM dssdb.dssgrp WHERE logname=%s LIMIT 1", (str(logname),))
164
+ row = cur.fetchone()
165
+ cur.close()
166
+ conn.close()
167
+ if row:
168
+ return row[0]
169
+ else:
170
+ raise ValueError(f"User logname '{logname}' not found in dssdb.dssgrp table.")
171
+ except Exception as e:
172
+ if 'server closed the connection unexpectedly' in str(e) and attempt < max_retries:
173
+ attempt += 1
174
+ time.sleep(2)
175
+ continue
176
+ raise
144
177
 
145
178
  def main():
146
179
  parser = argparse.ArgumentParser(description='Insert tar file summary into tfile table.')
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: rda_python_dsquasar
3
+ Version: 3.0.1
4
+ Summary: RDA Python package to backup and recover RDA data archives to and from GLOBUS Quasar backup server
5
+ Author-email: Zaihua Ji <zji@ucar.edu>
6
+ Project-URL: Homepage, https://github.com/NCAR/rda-python-dsquasar
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Requires-Python: >=3.7
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: rda_python_common
15
+ Requires-Dist: rda_python_dsarch
16
+ Dynamic: license-file
17
+
18
+ # rda_python_dsquasar
19
+
20
+ RDA Python package to back up and recover RDA data archives to and from the
21
+ GLOBUS Quasar backup server.
22
+
23
+ ## Programs
24
+
25
+ The package installs the following command-line utilities, all running as the
26
+ current user:
27
+
28
+ - `dsquasar` — back up and restore RDA dataset archives via Quasar
29
+ - `tacctar` — create tar bundles for Quasar archival
30
+ - `taccrec` — recover content from Quasar tar bundles
31
+
32
+ Run any program with `--help` (or `-h`) for full usage details.
33
+
34
+ ## Environment setup
35
+
36
+ Create a Python environment first; package installs in the next section run
37
+ inside whichever environment you activate here.
38
+
39
+ ### Option A — Python venv (DECS machines)
40
+
41
+ ```bash
42
+ python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
43
+ source $ENVHOME/bin/activate
44
+ ```
45
+
46
+ ### Option B — Conda (DAV/Casper)
47
+
48
+ ```bash
49
+ conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
50
+ conda activate $ENVHOME
51
+ ```
52
+
53
+ ## Installing rda-python-dsquasar
54
+
55
+ Pick whichever install mode fits your workflow. All variants pull in the
56
+ transitive dependencies (`rda_python_common`, `rda_python_dsarch`)
57
+ automatically.
58
+
59
+ For local development, clone this repo alongside your project and install it
60
+ in editable mode so that changes are picked up without re-installing:
61
+
62
+ ```bash
63
+ git clone https://github.com/NCAR/rda-python-dsquasar.git
64
+ cd rda-python-dsquasar
65
+ pip install -e .
66
+ ```
67
+
68
+ To test a specific branch (e.g. an in-progress feature or fix branch), pass
69
+ `-b/--branch` to `git clone`:
70
+
71
+ ```bash
72
+ git clone -b <branch-name> https://github.com/NCAR/rda-python-dsquasar.git
73
+ cd rda-python-dsquasar
74
+ pip install -e .
75
+ ```
76
+
77
+ For a regular (non-editable) install from a checkout:
78
+
79
+ ```bash
80
+ pip install /path/to/rda-python-dsquasar
81
+ ```
82
+
83
+ For a production install on a system that uses the published distribution:
84
+
85
+ ```bash
86
+ pip install rda_python_dsquasar
87
+ ```
@@ -1,18 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: rda_python_dsquasar
3
- Version: 2.0.11
4
- Summary: RDA Python package to backup and recover RDA data archives to and from GLOBUS Quasar backup server
5
- Author-email: Zaihua Ji <zji@ucar.edu>
6
- Project-URL: Homepage, https://github.com/NCAR/rda-python-dsquasar
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Operating System :: OS Independent
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Requires-Python: >=3.7
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: rda_python_common
15
- Requires-Dist: rda_python_dsarch
16
- Dynamic: license-file
17
-
18
- RDA python package to backup RDA dataset data onto Globus Quasar Server.
@@ -1 +0,0 @@
1
- RDA python package to backup RDA dataset data onto Globus Quasar Server.
@@ -1,18 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: rda_python_dsquasar
3
- Version: 2.0.11
4
- Summary: RDA Python package to backup and recover RDA data archives to and from GLOBUS Quasar backup server
5
- Author-email: Zaihua Ji <zji@ucar.edu>
6
- Project-URL: Homepage, https://github.com/NCAR/rda-python-dsquasar
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Operating System :: OS Independent
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Requires-Python: >=3.7
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: rda_python_common
15
- Requires-Dist: rda_python_dsarch
16
- Dynamic: license-file
17
-
18
- RDA python package to backup RDA dataset data onto Globus Quasar Server.