Fix fake_env, fix configparser issues, uniform 'open'.
- Update fake_env for compatibility with io. - Uniform open (through _my_open in content). - Fix read issue for config (although still using SafeConfigParser that is deprecated in py3).
This commit is contained in:
parent
d758df2ac9
commit
136b8f83dc
@ -1,10 +1,9 @@
|
||||
import os
|
||||
import collections
|
||||
|
||||
from .p3 import configparser
|
||||
from . import content
|
||||
from .p3 import configparser, _read_config
|
||||
|
||||
from .content import system_path, check_file
|
||||
from .content import check_file, _open
|
||||
|
||||
|
||||
# constant stuff (DFT = DEFAULT)
|
||||
@ -64,17 +63,15 @@ class Config(object):
|
||||
_config = self
|
||||
|
||||
def load(self, path=DFT_CONFIG_PATH):
|
||||
if not content.check_file(path, fail=False):
|
||||
if not check_file(path, fail=False):
|
||||
raise IOError(("The configuration file {} does not exist."
|
||||
" Did you run 'pubs init' ?").format(path))
|
||||
with open(content.system_path(path), 'r') as f:
|
||||
read = self._cfg.readfp(f)
|
||||
# if len(read) == 0:
|
||||
# raise IOError("Syntax error in {} config file. Aborting.".format(path))
|
||||
with _open(path, 'r') as f:
|
||||
_read_config(self._cfg, f)
|
||||
return self
|
||||
|
||||
def save(self, path=DFT_CONFIG_PATH):
|
||||
with open(content.system_path(path), 'w') as f:
|
||||
with _open(path, 'w') as f:
|
||||
self._cfg.write(f)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
|
@ -43,6 +43,10 @@ def system_path(path):
|
||||
return os.path.abspath(os.path.expanduser(path))
|
||||
|
||||
|
||||
def _open(path, mode):
|
||||
return io.open(system_path(path), mode, encoding=ENCODING)
|
||||
|
||||
|
||||
def check_file(path, fail=True):
|
||||
syspath = system_path(path)
|
||||
return (_check_system_path_exists(syspath, fail=fail)
|
||||
@ -57,14 +61,14 @@ def check_directory(path, fail=True):
|
||||
|
||||
def read_file(filepath):
|
||||
check_file(filepath)
|
||||
with io.open(system_path(filepath), 'r', encoding=ENCODING) as f:
|
||||
with _open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
return content
|
||||
|
||||
|
||||
def write_file(filepath, data):
|
||||
check_directory(os.path.dirname(filepath))
|
||||
with io.open(system_path(filepath), 'w', encoding=ENCODING) as f:
|
||||
with _open(filepath, 'w') as f:
|
||||
f.write(data)
|
||||
|
||||
|
||||
|
@ -1,25 +1,29 @@
|
||||
import io
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
import ConfigParser as configparser
|
||||
_read_config = configparser.SafeConfigParser.readfp
|
||||
input = raw_input
|
||||
ustr = unicode
|
||||
uchr = unichr
|
||||
from urlparse import urlparse
|
||||
from urllib2 import urlopen
|
||||
from httplib import HTTPConnection
|
||||
file = None
|
||||
_fake_stdio = io.BytesIO # Only for tests to capture std{out,err}
|
||||
else:
|
||||
import configparser
|
||||
_read_config = configparser.SafeConfigParser.read_file
|
||||
ustr = str
|
||||
uchr = chr
|
||||
file = None
|
||||
from urllib.parse import urlparse
|
||||
from urllib.request import urlopen
|
||||
from http.client import HTTPConnection
|
||||
_fake_stdio = io.StringIO # Only for tests to capture std{out,err}
|
||||
|
||||
configparser = configparser
|
||||
input = input
|
||||
file = file
|
||||
|
||||
|
||||
def isbasestr(obj):
|
||||
|
@ -2,6 +2,7 @@ import copy
|
||||
from dateutil.parser import parse as datetime_parse
|
||||
|
||||
from . import bibstruct
|
||||
from .p3 import ustr
|
||||
|
||||
|
||||
DEFAULT_META = {'docfile': None, 'tags': set()}
|
||||
@ -11,7 +12,7 @@ def _clean_metadata(metadata):
|
||||
meta = copy.deepcopy(DEFAULT_META)
|
||||
meta.update(metadata or {}) # handles None metadata
|
||||
meta['tags'] = set(meta.get('tags', [])) # tags should be a set
|
||||
if 'added' in meta and isinstance(meta['added'], basestring):
|
||||
if 'added' in meta and isinstance(meta['added'], ustr):
|
||||
meta['added'] = datetime_parse(meta['added'])
|
||||
return meta
|
||||
|
||||
|
@ -4,7 +4,6 @@ import sys
|
||||
|
||||
from .beets_ui import _encoding, input_
|
||||
from .content import editor_input
|
||||
from .p3 import ustr
|
||||
from . import color
|
||||
|
||||
# package-shared ui that can be accessed using :
|
||||
@ -39,10 +38,7 @@ class UI:
|
||||
is not in the terminal's encoding's character set, just silently
|
||||
replaces it.
|
||||
"""
|
||||
txt = [s.encode(self.encoding, 'replace')
|
||||
if isinstance(s, ustr) else s
|
||||
for s in strings]
|
||||
print(' '.join(txt))
|
||||
print(' '.join(strings).encode(self.encoding, 'replace'))
|
||||
|
||||
def input_choice(self, options, option_chars, default=None, question=''):
|
||||
"""Ask the user to chose between a set of options. The iser is asked
|
||||
|
3
setup.py
3
setup.py
@ -2,6 +2,7 @@
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
setup(name='pubs',
|
||||
version='4',
|
||||
author='Fabien Benureau, Olivier Mangin, Jonathan Grizou',
|
||||
@ -10,5 +11,5 @@ setup(name='pubs',
|
||||
description='research papers manager',
|
||||
requires=['pyyaml', 'bibtexparser', 'dateutil'],
|
||||
packages=find_packages(),
|
||||
scripts=['pubs/pubs']
|
||||
scripts=['pubs/pubs'],
|
||||
)
|
||||
|
@ -10,14 +10,13 @@ import fake_filesystem
|
||||
import fake_filesystem_shutil
|
||||
import fake_filesystem_glob
|
||||
|
||||
from pubs.p3 import input
|
||||
from pubs.p3 import input, _fake_stdio
|
||||
from pubs import content, filebroker
|
||||
|
||||
# code for fake fs
|
||||
|
||||
real_os = os
|
||||
real_open = open
|
||||
real_file = file
|
||||
real_shutil = shutil
|
||||
real_glob = glob
|
||||
real_io = io
|
||||
@ -41,7 +40,7 @@ ENCODING = 'utf8'
|
||||
|
||||
|
||||
class UnicodeStringIOWrapper(object):
|
||||
"""This is a hack because fake_filesystem does not provied mock of io.
|
||||
"""This is a hack because fake_filesystem does not provide mock of io.
|
||||
"""
|
||||
|
||||
override = ['read', 'readline', 'readlines', 'write', 'writelines']
|
||||
@ -55,6 +54,10 @@ class UnicodeStringIOWrapper(object):
|
||||
else:
|
||||
return self._strio.__getattribute__(name)
|
||||
|
||||
def __iter__(self):
|
||||
for l in self.readlines():
|
||||
yield l
|
||||
|
||||
def read(self, *args):
|
||||
return self._strio.read(*args).decode(ENCODING)
|
||||
|
||||
@ -78,13 +81,24 @@ class UnicodeStringIOWrapper(object):
|
||||
return self._strio.__exit__(*args)
|
||||
|
||||
|
||||
def _force_binary_mode(mode):
|
||||
if 'b' in mode:
|
||||
raise ValueError('Open should not happen in binary mode.')
|
||||
return mode + 'b'
|
||||
|
||||
|
||||
class FakeIO(object):
|
||||
|
||||
def __init__(self, fake_open):
|
||||
self.fake_open = fake_open
|
||||
|
||||
def open(self, *args, **kwargs):
|
||||
# Forces python3 mode for FakeFileOpen
|
||||
# Forces binary mode for FakeFileOpen
|
||||
args = list(args)
|
||||
if len(args) > 1:
|
||||
args[1] = _force_binary_mode(args[1])
|
||||
else:
|
||||
kwargs['mode'] = _force_binary_mode(kwargs.get('mode', 'r'))
|
||||
fakefs_stringio = self.fake_open.Call(*args, **kwargs)
|
||||
return UnicodeStringIOWrapper(fakefs_stringio)
|
||||
|
||||
@ -100,8 +114,6 @@ def create_fake_fs(module_list):
|
||||
|
||||
fake_fs.CreateDirectory(fake_os.path.expanduser('~'))
|
||||
|
||||
__builtins__.update({'open': fake_open, 'file': fake_open})
|
||||
|
||||
sys.modules['os'] = fake_os
|
||||
sys.modules['shutil'] = fake_shutil
|
||||
sys.modules['glob'] = fake_glob
|
||||
@ -111,7 +123,7 @@ def create_fake_fs(module_list):
|
||||
md.os = fake_os
|
||||
md.shutil = fake_shutil
|
||||
md.open = fake_open
|
||||
md.file = fake_open
|
||||
md.file = None
|
||||
md.io = fake_io
|
||||
|
||||
return {'fs': fake_fs,
|
||||
@ -125,10 +137,8 @@ def create_fake_fs(module_list):
|
||||
def unset_fake_fs(module_list):
|
||||
try:
|
||||
__builtins__.open = real_open
|
||||
__builtins__.file = real_file
|
||||
except AttributeError:
|
||||
__builtins__['open'] = real_open
|
||||
__builtins__['file'] = real_file
|
||||
|
||||
sys.modules['os'] = real_os
|
||||
sys.modules['shutil'] = real_shutil
|
||||
@ -139,7 +149,6 @@ def unset_fake_fs(module_list):
|
||||
md.os = real_os
|
||||
md.shutil = real_shutil
|
||||
md.open = real_open
|
||||
md.file = real_file
|
||||
md.io = real_io
|
||||
|
||||
|
||||
@ -163,8 +172,8 @@ def copy_dir(fs, real_dir, fake_dir = None):
|
||||
def redirect(f):
|
||||
def newf(*args, **kwargs):
|
||||
old_stderr, old_stdout = sys.stderr, sys.stdout
|
||||
stdout = io.BytesIO()
|
||||
stderr = io.BytesIO()
|
||||
stdout = _fake_stdio()
|
||||
stderr = _fake_stdio()
|
||||
sys.stdout, sys.stderr = stdout, stderr
|
||||
try:
|
||||
return f(*args, **kwargs), stdout, stderr
|
||||
@ -190,7 +199,7 @@ class FakeInput():
|
||||
Then :
|
||||
input() returns 'yes'
|
||||
input() returns 'no'
|
||||
input() raise IndexError
|
||||
input() raises IndexError
|
||||
"""
|
||||
|
||||
def __init__(self, inputs, module_list=tuple()):
|
||||
|
@ -34,7 +34,6 @@ class TestEnDecode(unittest.TestCase):
|
||||
data = decoder.encode_metadata(dummy_metadata)
|
||||
self.assertIsInstance(data, ustr)
|
||||
|
||||
|
||||
def test_endecode_bibtex(self):
|
||||
decoder = endecoder.EnDecoder()
|
||||
entry = decoder.decode_bibdata(bibtex_raw0)
|
||||
|
@ -29,11 +29,11 @@ class TestFileBroker(fake_env.TestFakeFs):
|
||||
fake_env.copy_dir(self.fs, os.path.join(os.path.dirname(__file__), 'testrepo'), 'testrepo')
|
||||
fb = filebroker.FileBroker('testrepo', create = True)
|
||||
|
||||
with open('testrepo/bib/Page99.bib', 'r') as f:
|
||||
self.assertEqual(fb.pull_bibfile('Page99'), f.read())
|
||||
bib_content = content.read_file('testrepo/bib/Page99.bib')
|
||||
self.assertEqual(fb.pull_bibfile('Page99'), bib_content)
|
||||
|
||||
with open('testrepo/meta/Page99.yaml', 'r') as f:
|
||||
self.assertEqual(fb.pull_metafile('Page99'), f.read())
|
||||
meta_content = content.read_file('testrepo/meta/Page99.yaml')
|
||||
self.assertEqual(fb.pull_metafile('Page99'), meta_content)
|
||||
|
||||
def test_errors(self):
|
||||
|
||||
|
@ -66,12 +66,12 @@ class CommandTestCase(unittest.TestCase):
|
||||
In the latter case, the command is :
|
||||
1. a string reprensenting the command to execute
|
||||
2. the user inputs to feed to the command during execution
|
||||
3. the output excpected, verified with assertEqual
|
||||
3. the output expected, verified with assertEqual
|
||||
|
||||
"""
|
||||
outs = []
|
||||
for cmd in cmds:
|
||||
if hasattr(cmd, '__iter__'):
|
||||
if not isinstance(cmd, p3.ustr):
|
||||
if len(cmd) == 2:
|
||||
input = fake_env.FakeInput(cmd[1], [content, uis, beets_ui, p3])
|
||||
input.as_global()
|
||||
@ -293,6 +293,7 @@ class TestUsecase(DataCommandTestCase):
|
||||
print(self.fs['os'].listdir(docdir))
|
||||
self.assertNotIn('turing-mind-1950.pdf', self.fs['os'].listdir(docdir))
|
||||
|
||||
|
||||
def test_tag_list(self):
|
||||
correct = [b'Initializing pubs in /paper_first\n',
|
||||
b'',
|
||||
|
Loading…
x
Reference in New Issue
Block a user