1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

"""A file interface for handling local and remote data files. 

 

The goal of datasource is to abstract some of the file system operations 

when dealing with data files so the researcher doesn't have to know all the 

low-level details. Through datasource, a researcher can obtain and use a 

file with one function call, regardless of location of the file. 

 

DataSource is meant to augment standard python libraries, not replace them. 

It should work seamlessly with standard file IO operations and the os 

module. 

 

DataSource files can originate locally or remotely: 

 

- local files : '/home/guido/src/local/data.txt' 

- URLs (http, ftp, ...) : 'http://www.scipy.org/not/real/data.txt' 

 

DataSource files can also be compressed or uncompressed. Currently only 

gzip, bz2 and xz are supported. 

 

Example:: 

 

>>> # Create a DataSource, use os.curdir (default) for local storage. 

>>> ds = datasource.DataSource() 

>>> 

>>> # Open a remote file. 

>>> # DataSource downloads the file, stores it locally in: 

>>> # './www.google.com/index.html' 

>>> # opens the file and returns a file object. 

>>> fp = ds.open('http://www.google.com/index.html') 

>>> 

>>> # Use the file as you normally would 

>>> fp.read() 

>>> fp.close() 

 

""" 

from __future__ import division, absolute_import, print_function 

 

import os 

import sys 

import warnings 

import shutil 

import io 

 

from numpy.core.overrides import set_module 

 

 

_open = open 

 

 

def _check_mode(mode, encoding, newline): 

"""Check mode and that encoding and newline are compatible. 

 

Parameters 

---------- 

mode : str 

File open mode. 

encoding : str 

File encoding. 

newline : str 

Newline for text files. 

 

""" 

if "t" in mode: 

if "b" in mode: 

raise ValueError("Invalid mode: %r" % (mode,)) 

else: 

if encoding is not None: 

raise ValueError("Argument 'encoding' not supported in binary mode") 

if newline is not None: 

raise ValueError("Argument 'newline' not supported in binary mode") 

 

 

def _python2_bz2open(fn, mode, encoding, newline): 

"""Wrapper to open bz2 in text mode. 

 

Parameters 

---------- 

fn : str 

File name 

mode : {'r', 'w'} 

File mode. Note that bz2 Text files are not supported. 

encoding : str 

Ignored, text bz2 files not supported in Python2. 

newline : str 

Ignored, text bz2 files not supported in Python2. 

""" 

import bz2 

 

_check_mode(mode, encoding, newline) 

 

if "t" in mode: 

# BZ2File is missing necessary functions for TextIOWrapper 

warnings.warn("Assuming latin1 encoding for bz2 text file in Python2", 

RuntimeWarning, stacklevel=5) 

mode = mode.replace("t", "") 

return bz2.BZ2File(fn, mode) 

 

def _python2_gzipopen(fn, mode, encoding, newline): 

""" Wrapper to open gzip in text mode. 

 

Parameters 

---------- 

fn : str, bytes, file 

File path or opened file. 

mode : str 

File mode. The actual files are opened as binary, but will decoded 

using the specified `encoding` and `newline`. 

encoding : str 

Encoding to be used when reading/writing as text. 

newline : str 

Newline to be used when reading/writing as text. 

 

""" 

import gzip 

# gzip is lacking read1 needed for TextIOWrapper 

class GzipWrap(gzip.GzipFile): 

def read1(self, n): 

return self.read(n) 

 

_check_mode(mode, encoding, newline) 

 

gz_mode = mode.replace("t", "") 

 

if isinstance(fn, (str, bytes)): 

binary_file = GzipWrap(fn, gz_mode) 

elif hasattr(fn, "read") or hasattr(fn, "write"): 

binary_file = GzipWrap(None, gz_mode, fileobj=fn) 

else: 

raise TypeError("filename must be a str or bytes object, or a file") 

 

if "t" in mode: 

return io.TextIOWrapper(binary_file, encoding, newline=newline) 

else: 

return binary_file 

 

 

# Using a class instead of a module-level dictionary 

# to reduce the initial 'import numpy' overhead by 

# deferring the import of lzma, bz2 and gzip until needed 

 

# TODO: .zip support, .tar support? 

class _FileOpeners(object): 

""" 

Container for different methods to open (un-)compressed files. 

 

`_FileOpeners` contains a dictionary that holds one method for each 

supported file format. Attribute lookup is implemented in such a way 

that an instance of `_FileOpeners` itself can be indexed with the keys 

of that dictionary. Currently uncompressed files as well as files 

compressed with ``gzip``, ``bz2`` or ``xz`` compression are supported. 

 

Notes 

----- 

`_file_openers`, an instance of `_FileOpeners`, is made available for 

use in the `_datasource` module. 

 

Examples 

-------- 

>>> np.lib._datasource._file_openers.keys() 

[None, '.bz2', '.gz', '.xz', '.lzma'] 

>>> np.lib._datasource._file_openers['.gz'] is gzip.open 

True 

 

""" 

 

def __init__(self): 

self._loaded = False 

self._file_openers = {None: io.open} 

 

def _load(self): 

if self._loaded: 

return 

 

try: 

import bz2 

if sys.version_info[0] >= 3: 

self._file_openers[".bz2"] = bz2.open 

else: 

self._file_openers[".bz2"] = _python2_bz2open 

except ImportError: 

pass 

 

try: 

import gzip 

if sys.version_info[0] >= 3: 

self._file_openers[".gz"] = gzip.open 

else: 

self._file_openers[".gz"] = _python2_gzipopen 

except ImportError: 

pass 

 

try: 

import lzma 

self._file_openers[".xz"] = lzma.open 

self._file_openers[".lzma"] = lzma.open 

except (ImportError, AttributeError): 

# There are incompatible backports of lzma that do not have the 

# lzma.open attribute, so catch that as well as ImportError. 

pass 

 

self._loaded = True 

 

def keys(self): 

""" 

Return the keys of currently supported file openers. 

 

Parameters 

---------- 

None 

 

Returns 

------- 

keys : list 

The keys are None for uncompressed files and the file extension 

strings (i.e. ``'.gz'``, ``'.xz'``) for supported compression 

methods. 

 

""" 

self._load() 

return list(self._file_openers.keys()) 

 

def __getitem__(self, key): 

self._load() 

return self._file_openers[key] 

 

_file_openers = _FileOpeners() 

 

def open(path, mode='r', destpath=os.curdir, encoding=None, newline=None): 

""" 

Open `path` with `mode` and return the file object. 

 

If ``path`` is an URL, it will be downloaded, stored in the 

`DataSource` `destpath` directory and opened from there. 

 

Parameters 

---------- 

path : str 

Local file path or URL to open. 

mode : str, optional 

Mode to open `path`. Mode 'r' for reading, 'w' for writing, 'a' to 

append. Available modes depend on the type of object specified by 

path. Default is 'r'. 

destpath : str, optional 

Path to the directory where the source file gets downloaded to for 

use. If `destpath` is None, a temporary directory will be created. 

The default path is the current directory. 

encoding : {None, str}, optional 

Open text file with given encoding. The default encoding will be 

what `io.open` uses. 

newline : {None, str}, optional 

Newline to use when reading text file. 

 

Returns 

------- 

out : file object 

The opened file. 

 

Notes 

----- 

This is a convenience function that instantiates a `DataSource` and 

returns the file object from ``DataSource.open(path)``. 

 

""" 

 

ds = DataSource(destpath) 

return ds.open(path, mode, encoding=encoding, newline=newline) 

 

 

@set_module('numpy') 

class DataSource(object): 

""" 

DataSource(destpath='.') 

 

A generic data source file (file, http, ftp, ...). 

 

DataSources can be local files or remote files/URLs. The files may 

also be compressed or uncompressed. DataSource hides some of the 

low-level details of downloading the file, allowing you to simply pass 

in a valid file path (or URL) and obtain a file object. 

 

Parameters 

---------- 

destpath : str or None, optional 

Path to the directory where the source file gets downloaded to for 

use. If `destpath` is None, a temporary directory will be created. 

The default path is the current directory. 

 

Notes 

----- 

URLs require a scheme string (``http://``) to be used, without it they 

will fail:: 

 

>>> repos = DataSource() 

>>> repos.exists('www.google.com/index.html') 

False 

>>> repos.exists('http://www.google.com/index.html') 

True 

 

Temporary directories are deleted when the DataSource is deleted. 

 

Examples 

-------- 

:: 

 

>>> ds = DataSource('/home/guido') 

>>> urlname = 'http://www.google.com/index.html' 

>>> gfile = ds.open('http://www.google.com/index.html') # remote file 

>>> ds.abspath(urlname) 

'/home/guido/www.google.com/site/index.html' 

 

>>> ds = DataSource(None) # use with temporary file 

>>> ds.open('/home/guido/foobar.txt') 

<open file '/home/guido.foobar.txt', mode 'r' at 0x91d4430> 

>>> ds.abspath('/home/guido/foobar.txt') 

'/tmp/tmpy4pgsP/home/guido/foobar.txt' 

 

""" 

 

def __init__(self, destpath=os.curdir): 

"""Create a DataSource with a local path at destpath.""" 

if destpath: 

self._destpath = os.path.abspath(destpath) 

self._istmpdest = False 

else: 

import tempfile # deferring import to improve startup time 

self._destpath = tempfile.mkdtemp() 

self._istmpdest = True 

 

def __del__(self): 

# Remove temp directories 

if hasattr(self, '_istmpdest') and self._istmpdest: 

shutil.rmtree(self._destpath) 

 

def _iszip(self, filename): 

"""Test if the filename is a zip file by looking at the file extension. 

 

""" 

fname, ext = os.path.splitext(filename) 

return ext in _file_openers.keys() 

 

def _iswritemode(self, mode): 

"""Test if the given mode will open a file for writing.""" 

 

# Currently only used to test the bz2 files. 

_writemodes = ("w", "+") 

for c in mode: 

if c in _writemodes: 

return True 

return False 

 

def _splitzipext(self, filename): 

"""Split zip extension from filename and return filename. 

 

*Returns*: 

base, zip_ext : {tuple} 

 

""" 

 

if self._iszip(filename): 

return os.path.splitext(filename) 

else: 

return filename, None 

 

def _possible_names(self, filename): 

"""Return a tuple containing compressed filename variations.""" 

names = [filename] 

if not self._iszip(filename): 

for zipext in _file_openers.keys(): 

if zipext: 

names.append(filename+zipext) 

return names 

 

def _isurl(self, path): 

"""Test if path is a net location. Tests the scheme and netloc.""" 

 

# We do this here to reduce the 'import numpy' initial import time. 

if sys.version_info[0] >= 3: 

from urllib.parse import urlparse 

else: 

from urlparse import urlparse 

 

# BUG : URLs require a scheme string ('http://') to be used. 

# www.google.com will fail. 

# Should we prepend the scheme for those that don't have it and 

# test that also? Similar to the way we append .gz and test for 

# for compressed versions of files. 

 

scheme, netloc, upath, uparams, uquery, ufrag = urlparse(path) 

return bool(scheme and netloc) 

 

def _cache(self, path): 

"""Cache the file specified by path. 

 

Creates a copy of the file in the datasource cache. 

 

""" 

# We import these here because importing urllib2 is slow and 

# a significant fraction of numpy's total import time. 

if sys.version_info[0] >= 3: 

from urllib.request import urlopen 

from urllib.error import URLError 

else: 

from urllib2 import urlopen 

from urllib2 import URLError 

 

upath = self.abspath(path) 

 

# ensure directory exists 

if not os.path.exists(os.path.dirname(upath)): 

os.makedirs(os.path.dirname(upath)) 

 

# TODO: Doesn't handle compressed files! 

if self._isurl(path): 

try: 

openedurl = urlopen(path) 

f = _open(upath, 'wb') 

try: 

shutil.copyfileobj(openedurl, f) 

finally: 

f.close() 

openedurl.close() 

except URLError: 

raise URLError("URL not found: %s" % path) 

else: 

shutil.copyfile(path, upath) 

return upath 

 

def _findfile(self, path): 

"""Searches for ``path`` and returns full path if found. 

 

If path is an URL, _findfile will cache a local copy and return the 

path to the cached file. If path is a local file, _findfile will 

return a path to that local file. 

 

The search will include possible compressed versions of the file 

and return the first occurrence found. 

 

""" 

 

# Build list of possible local file paths 

if not self._isurl(path): 

# Valid local paths 

filelist = self._possible_names(path) 

# Paths in self._destpath 

filelist += self._possible_names(self.abspath(path)) 

else: 

# Cached URLs in self._destpath 

filelist = self._possible_names(self.abspath(path)) 

# Remote URLs 

filelist = filelist + self._possible_names(path) 

 

for name in filelist: 

if self.exists(name): 

if self._isurl(name): 

name = self._cache(name) 

return name 

return None 

 

def abspath(self, path): 

""" 

Return absolute path of file in the DataSource directory. 

 

If `path` is an URL, then `abspath` will return either the location 

the file exists locally or the location it would exist when opened 

using the `open` method. 

 

Parameters 

---------- 

path : str 

Can be a local file or a remote URL. 

 

Returns 

------- 

out : str 

Complete path, including the `DataSource` destination directory. 

 

Notes 

----- 

The functionality is based on `os.path.abspath`. 

 

""" 

# We do this here to reduce the 'import numpy' initial import time. 

if sys.version_info[0] >= 3: 

from urllib.parse import urlparse 

else: 

from urlparse import urlparse 

 

# TODO: This should be more robust. Handles case where path includes 

# the destpath, but not other sub-paths. Failing case: 

# path = /home/guido/datafile.txt 

# destpath = /home/alex/ 

# upath = self.abspath(path) 

# upath == '/home/alex/home/guido/datafile.txt' 

 

# handle case where path includes self._destpath 

splitpath = path.split(self._destpath, 2) 

if len(splitpath) > 1: 

path = splitpath[1] 

scheme, netloc, upath, uparams, uquery, ufrag = urlparse(path) 

netloc = self._sanitize_relative_path(netloc) 

upath = self._sanitize_relative_path(upath) 

return os.path.join(self._destpath, netloc, upath) 

 

def _sanitize_relative_path(self, path): 

"""Return a sanitised relative path for which 

os.path.abspath(os.path.join(base, path)).startswith(base) 

""" 

last = None 

path = os.path.normpath(path) 

while path != last: 

last = path 

# Note: os.path.join treats '/' as os.sep on Windows 

path = path.lstrip(os.sep).lstrip('/') 

path = path.lstrip(os.pardir).lstrip('..') 

drive, path = os.path.splitdrive(path) # for Windows 

return path 

 

def exists(self, path): 

""" 

Test if path exists. 

 

Test if `path` exists as (and in this order): 

 

- a local file. 

- a remote URL that has been downloaded and stored locally in the 

`DataSource` directory. 

- a remote URL that has not been downloaded, but is valid and 

accessible. 

 

Parameters 

---------- 

path : str 

Can be a local file or a remote URL. 

 

Returns 

------- 

out : bool 

True if `path` exists. 

 

Notes 

----- 

When `path` is an URL, `exists` will return True if it's either 

stored locally in the `DataSource` directory, or is a valid remote 

URL. `DataSource` does not discriminate between the two, the file 

is accessible if it exists in either location. 

 

""" 

 

# First test for local path 

if os.path.exists(path): 

return True 

 

# We import this here because importing urllib2 is slow and 

# a significant fraction of numpy's total import time. 

if sys.version_info[0] >= 3: 

from urllib.request import urlopen 

from urllib.error import URLError 

else: 

from urllib2 import urlopen 

from urllib2 import URLError 

 

# Test cached url 

upath = self.abspath(path) 

if os.path.exists(upath): 

return True 

 

# Test remote url 

if self._isurl(path): 

try: 

netfile = urlopen(path) 

netfile.close() 

del(netfile) 

return True 

except URLError: 

return False 

return False 

 

def open(self, path, mode='r', encoding=None, newline=None): 

""" 

Open and return file-like object. 

 

If `path` is an URL, it will be downloaded, stored in the 

`DataSource` directory and opened from there. 

 

Parameters 

---------- 

path : str 

Local file path or URL to open. 

mode : {'r', 'w', 'a'}, optional 

Mode to open `path`. Mode 'r' for reading, 'w' for writing, 

'a' to append. Available modes depend on the type of object 

specified by `path`. Default is 'r'. 

encoding : {None, str}, optional 

Open text file with given encoding. The default encoding will be 

what `io.open` uses. 

newline : {None, str}, optional 

Newline to use when reading text file. 

 

Returns 

------- 

out : file object 

File object. 

 

""" 

 

# TODO: There is no support for opening a file for writing which 

# doesn't exist yet (creating a file). Should there be? 

 

# TODO: Add a ``subdir`` parameter for specifying the subdirectory 

# used to store URLs in self._destpath. 

 

if self._isurl(path) and self._iswritemode(mode): 

raise ValueError("URLs are not writeable") 

 

# NOTE: _findfile will fail on a new file opened for writing. 

found = self._findfile(path) 

if found: 

_fname, ext = self._splitzipext(found) 

if ext == 'bz2': 

mode.replace("+", "") 

return _file_openers[ext](found, mode=mode, 

encoding=encoding, newline=newline) 

else: 

raise IOError("%s not found." % path) 

 

 

class Repository (DataSource): 

""" 

Repository(baseurl, destpath='.') 

 

A data repository where multiple DataSource's share a base 

URL/directory. 

 

`Repository` extends `DataSource` by prepending a base URL (or 

directory) to all the files it handles. Use `Repository` when you will 

be working with multiple files from one base URL. Initialize 

`Repository` with the base URL, then refer to each file by its filename 

only. 

 

Parameters 

---------- 

baseurl : str 

Path to the local directory or remote location that contains the 

data files. 

destpath : str or None, optional 

Path to the directory where the source file gets downloaded to for 

use. If `destpath` is None, a temporary directory will be created. 

The default path is the current directory. 

 

Examples 

-------- 

To analyze all files in the repository, do something like this 

(note: this is not self-contained code):: 

 

>>> repos = np.lib._datasource.Repository('/home/user/data/dir/') 

>>> for filename in filelist: 

... fp = repos.open(filename) 

... fp.analyze() 

... fp.close() 

 

Similarly you could use a URL for a repository:: 

 

>>> repos = np.lib._datasource.Repository('http://www.xyz.edu/data') 

 

""" 

 

def __init__(self, baseurl, destpath=os.curdir): 

"""Create a Repository with a shared url or directory of baseurl.""" 

DataSource.__init__(self, destpath=destpath) 

self._baseurl = baseurl 

 

def __del__(self): 

DataSource.__del__(self) 

 

def _fullpath(self, path): 

"""Return complete path for path. Prepends baseurl if necessary.""" 

splitpath = path.split(self._baseurl, 2) 

if len(splitpath) == 1: 

result = os.path.join(self._baseurl, path) 

else: 

result = path # path contains baseurl already 

return result 

 

def _findfile(self, path): 

"""Extend DataSource method to prepend baseurl to ``path``.""" 

return DataSource._findfile(self, self._fullpath(path)) 

 

def abspath(self, path): 

""" 

Return absolute path of file in the Repository directory. 

 

If `path` is an URL, then `abspath` will return either the location 

the file exists locally or the location it would exist when opened 

using the `open` method. 

 

Parameters 

---------- 

path : str 

Can be a local file or a remote URL. This may, but does not 

have to, include the `baseurl` with which the `Repository` was 

initialized. 

 

Returns 

------- 

out : str 

Complete path, including the `DataSource` destination directory. 

 

""" 

return DataSource.abspath(self, self._fullpath(path)) 

 

def exists(self, path): 

""" 

Test if path exists prepending Repository base URL to path. 

 

Test if `path` exists as (and in this order): 

 

- a local file. 

- a remote URL that has been downloaded and stored locally in the 

`DataSource` directory. 

- a remote URL that has not been downloaded, but is valid and 

accessible. 

 

Parameters 

---------- 

path : str 

Can be a local file or a remote URL. This may, but does not 

have to, include the `baseurl` with which the `Repository` was 

initialized. 

 

Returns 

------- 

out : bool 

True if `path` exists. 

 

Notes 

----- 

When `path` is an URL, `exists` will return True if it's either 

stored locally in the `DataSource` directory, or is a valid remote 

URL. `DataSource` does not discriminate between the two, the file 

is accessible if it exists in either location. 

 

""" 

return DataSource.exists(self, self._fullpath(path)) 

 

def open(self, path, mode='r', encoding=None, newline=None): 

""" 

Open and return file-like object prepending Repository base URL. 

 

If `path` is an URL, it will be downloaded, stored in the 

DataSource directory and opened from there. 

 

Parameters 

---------- 

path : str 

Local file path or URL to open. This may, but does not have to, 

include the `baseurl` with which the `Repository` was 

initialized. 

mode : {'r', 'w', 'a'}, optional 

Mode to open `path`. Mode 'r' for reading, 'w' for writing, 

'a' to append. Available modes depend on the type of object 

specified by `path`. Default is 'r'. 

encoding : {None, str}, optional 

Open text file with given encoding. The default encoding will be 

what `io.open` uses. 

newline : {None, str}, optional 

Newline to use when reading text file. 

 

Returns 

------- 

out : file object 

File object. 

 

""" 

return DataSource.open(self, self._fullpath(path), mode, 

encoding=encoding, newline=newline) 

 

def listdir(self): 

""" 

List files in the source Repository. 

 

Returns 

------- 

files : list of str 

List of file names (not containing a directory part). 

 

Notes 

----- 

Does not currently work for remote repositories. 

 

""" 

if self._isurl(self._baseurl): 

raise NotImplementedError( 

"Directory listing of URLs, not supported yet.") 

else: 

return os.listdir(self._baseurl)