##// END OF EJS Templates
packages: move the str utils to it's own module
super-admin -
r1060:680d7e36 python3
parent child Browse files
Show More
@@ -0,0 +1,127 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2020 RhodeCode GmbH
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 import logging
19
20
21 log = logging.getLogger(__name__)
22
23
24 def safe_int(val, default=None) -> int:
25 """
26 Returns int() of val if val is not convertable to int use default
27 instead
28
29 :param val:
30 :param default:
31 """
32
33 try:
34 val = int(val)
35 except (ValueError, TypeError):
36 val = default
37
38 return val
39
40
41 def safe_str(str_, to_encoding=None) -> str:
42 """
43 safe str function. Does few trick to turn unicode_ into string
44
45 :param str_: str to encode
46 :param to_encoding: encode to this type UTF8 default
47 :rtype: str
48 :returns: str object
49 """
50 if isinstance(str_, str):
51 return str_
52
53 # if it's bytes cast to str
54 if not isinstance(str_, bytes):
55 return str(str_)
56
57 to_encoding = to_encoding or ['utf8']
58 if not isinstance(to_encoding, (list, tuple)):
59 to_encoding = [to_encoding]
60
61 for enc in to_encoding:
62 try:
63 return str(str_, enc)
64 except UnicodeDecodeError:
65 pass
66
67 return str(str_, to_encoding[0], 'replace')
68
69
70 def safe_bytes(str_, from_encoding=None) -> bytes:
71 """
72 safe bytes function. Does few trick to turn str_ into bytes string:
73
74 :param str_: string to decode
75 :param from_encoding: encode from this type UTF8 default
76 :rtype: unicode
77 :returns: unicode object
78 """
79 if isinstance(str_, bytes):
80 return str_
81
82 if not isinstance(str_, str):
83 raise ValueError('safe_bytes cannot convert other types than str: got: {}'.format(type(str_)))
84
85 from_encoding = from_encoding or ['utf8']
86 if not isinstance(from_encoding, (list, tuple)):
87 from_encoding = [from_encoding]
88
89 for enc in from_encoding:
90 try:
91 return str_.encode(enc)
92 except UnicodeDecodeError:
93 pass
94
95 return str_.encode(from_encoding[0], 'replace')
96
97
98 def ascii_bytes(str_, allow_bytes=False) -> bytes:
99 """
100 Simple conversion from str to bytes, with assumption that str_ is pure ASCII.
101 Fails with UnicodeError on invalid input.
102 This should be used where encoding and "safe" ambiguity should be avoided.
103 Where strings already have been encoded in other ways but still are unicode
104 string - for example to hex, base64, json, urlencoding, or are known to be
105 identifiers.
106 """
107 if allow_bytes and isinstance(str_, bytes):
108 return str_
109
110 if not isinstance(str_, str):
111 raise ValueError('ascii_bytes cannot convert other types than str: got: {}'.format(type(str_)))
112 return str_.encode('ascii')
113
114
115 def ascii_str(str_):
116 """
117 Simple conversion from bytes to str, with assumption that str_ is pure ASCII.
118 Fails with UnicodeError on invalid input.
119 This should be used where encoding and "safe" ambiguity should be avoided.
120 Where strings are encoded but also in other ways are known to be ASCII, and
121 where a unicode string is wanted without caring about encoding. For example
122 to hex, base64, urlencoding, or are known to be identifiers.
123 """
124
125 if not isinstance(str_, bytes):
126 raise ValueError('ascii_str cannot convert other types than bytes: got: {}'.format(type(str_)))
127 return str_.decode('ascii')
@@ -28,7 +28,7 b' from pyramid.httpexceptions import ('
28 from vcsserver.lib.rc_json import json
28 from vcsserver.lib.rc_json import json
29 from vcsserver.git_lfs.lib import OidHandler, LFSOidStore
29 from vcsserver.git_lfs.lib import OidHandler, LFSOidStore
30 from vcsserver.git_lfs.utils import safe_result, get_cython_compat_decorator
30 from vcsserver.git_lfs.utils import safe_result, get_cython_compat_decorator
31 from vcsserver.utils import safe_int
31 from vcsserver.str_utils import safe_int
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
@@ -20,7 +20,7 b' import pytest'
20 from webtest.app import TestApp as WebObTestApp
20 from webtest.app import TestApp as WebObTestApp
21
21
22 from vcsserver.lib.rc_json import json
22 from vcsserver.lib.rc_json import json
23 from vcsserver.utils import safe_bytes
23 from vcsserver.str_utils import safe_bytes
24 from vcsserver.git_lfs.app import create_app
24 from vcsserver.git_lfs.app import create_app
25
25
26
26
@@ -17,7 +17,7 b''
17
17
18 import os
18 import os
19 import pytest
19 import pytest
20 from vcsserver.utils import safe_bytes
20 from vcsserver.str_utils import safe_bytes
21 from vcsserver.git_lfs.lib import OidHandler, LFSOidStore
21 from vcsserver.git_lfs.lib import OidHandler, LFSOidStore
22
22
23
23
@@ -24,7 +24,7 b' from mercurial import demandimport'
24
24
25 # patch demandimport, due to bug in mercurial when it always triggers
25 # patch demandimport, due to bug in mercurial when it always triggers
26 # demandimport.enable()
26 # demandimport.enable()
27 from vcsserver.utils import safe_bytes
27 from vcsserver.str_utils import safe_bytes
28
28
29 demandimport.enable = lambda *args, **kwargs: 1
29 demandimport.enable = lambda *args, **kwargs: 1
30
30
@@ -25,7 +25,7 b' import logging'
25 import pkg_resources
25 import pkg_resources
26
26
27 import vcsserver
27 import vcsserver
28 from vcsserver.utils import safe_bytes
28 from vcsserver.str_utils import safe_bytes
29
29
30 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
31
31
@@ -34,7 +34,7 b' import mercurial.node'
34
34
35 from vcsserver.lib.rc_json import json
35 from vcsserver.lib.rc_json import json
36 from vcsserver import exceptions, subprocessio, settings
36 from vcsserver import exceptions, subprocessio, settings
37 from vcsserver.utils import safe_bytes
37 from vcsserver.str_utils import safe_bytes
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
@@ -39,7 +39,7 b' from pyramid.response import Response'
39
39
40 from vcsserver.lib.rc_json import json
40 from vcsserver.lib.rc_json import json
41 from vcsserver.config.settings_maker import SettingsMaker
41 from vcsserver.config.settings_maker import SettingsMaker
42 from vcsserver.utils import safe_int
42 from vcsserver.str_utils import safe_int
43 from vcsserver.lib.statsd_client import StatsdClient
43 from vcsserver.lib.statsd_client import StatsdClient
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
@@ -22,7 +22,7 b' import logging'
22
22
23 from repoze.lru import LRUCache
23 from repoze.lru import LRUCache
24
24
25 from vcsserver.utils import safe_str
25 from vcsserver.str_utils import safe_str
26
26
27 log = logging.getLogger(__name__)
27 log = logging.getLogger(__name__)
28
28
@@ -33,7 +33,7 b' from dogpile.cache.util import memoized_'
33 from pyramid.settings import asbool
33 from pyramid.settings import asbool
34
34
35 from vcsserver.lib.memory_lru_dict import LRUDict, LRUDictDebug
35 from vcsserver.lib.memory_lru_dict import LRUDict, LRUDictDebug
36 from vcsserver.utils import safe_str
36 from vcsserver.str_utils import safe_str
37
37
38
38
39 _default_max_size = 1024
39 _default_max_size = 1024
@@ -23,7 +23,8 b' import decorator'
23
23
24 from dogpile.cache import CacheRegion
24 from dogpile.cache import CacheRegion
25
25
26 from vcsserver.utils import safe_bytes, sha1
26 from vcsserver.str_utils import safe_bytes
27 from vcsserver.utils import sha1
27 from vcsserver.lib.rc_cache import region_meta
28 from vcsserver.lib.rc_cache import region_meta
28
29
29 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
@@ -24,7 +24,7 b' from svn import ra'
24
24
25 from mercurial import error
25 from mercurial import error
26
26
27 from vcsserver.utils import safe_bytes
27 from vcsserver.str_utils import safe_bytes
28
28
29 core.svn_config_ensure(None)
29 core.svn_config_ensure(None)
30 svn_config = core.svn_config_get_config(None)
30 svn_config = core.svn_config_get_config(None)
@@ -27,7 +27,7 b' from webob import Request, Response, exc'
27
27
28 from vcsserver.lib.rc_json import json
28 from vcsserver.lib.rc_json import json
29 from vcsserver import hooks, subprocessio
29 from vcsserver import hooks, subprocessio
30 from vcsserver.utils import ascii_bytes
30 from vcsserver.str_utils import ascii_bytes
31
31
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
@@ -40,7 +40,7 b' from dulwich.repo import Repo as Dulwich'
40 from dulwich.server import update_server_info
40 from dulwich.server import update_server_info
41
41
42 from vcsserver import exceptions, settings, subprocessio
42 from vcsserver import exceptions, settings, subprocessio
43 from vcsserver.utils import safe_str, safe_int
43 from vcsserver.str_utils import safe_str, safe_int
44 from vcsserver.base import RepoFactory, obfuscate_qs, ArchiveNode, archive_repo
44 from vcsserver.base import RepoFactory, obfuscate_qs, ArchiveNode, archive_repo
45 from vcsserver.hgcompat import (
45 from vcsserver.hgcompat import (
46 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler)
46 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler)
@@ -39,7 +39,7 b' from vcsserver.hgcompat import ('
39 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
39 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
40 RepoLookupError, InterventionRequired, RequirementError,
40 RepoLookupError, InterventionRequired, RequirementError,
41 alwaysmatcher, patternmatcher, hgutil, hgext_strip)
41 alwaysmatcher, patternmatcher, hgutil, hgext_strip)
42 from vcsserver.utils import ascii_bytes, ascii_str, safe_str, safe_bytes
42 from vcsserver.str_utils import ascii_bytes, ascii_str, safe_str, safe_bytes
43 from vcsserver.vcs_base import RemoteBase
43 from vcsserver.vcs_base import RemoteBase
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
@@ -38,7 +38,7 b' import svn.repos'
38 from vcsserver import svn_diff, exceptions, subprocessio, settings
38 from vcsserver import svn_diff, exceptions, subprocessio, settings
39 from vcsserver.base import RepoFactory, raise_from_original, ArchiveNode, archive_repo
39 from vcsserver.base import RepoFactory, raise_from_original, ArchiveNode, archive_repo
40 from vcsserver.exceptions import NoContentException
40 from vcsserver.exceptions import NoContentException
41 from vcsserver.utils import safe_str
41 from vcsserver.str_utils import safe_str
42 from vcsserver.vcs_base import RemoteBase
42 from vcsserver.vcs_base import RemoteBase
43 from vcsserver.lib.svnremoterepo import svnremoterepo
43 from vcsserver.lib.svnremoterepo import svnremoterepo
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
@@ -27,7 +27,7 b' import mercurial.hgweb.hgweb_mod'
27 import webob.exc
27 import webob.exc
28
28
29 from vcsserver import pygrack, exceptions, settings, git_lfs
29 from vcsserver import pygrack, exceptions, settings, git_lfs
30 from vcsserver.utils import ascii_bytes, safe_bytes
30 from vcsserver.str_utils import ascii_bytes, safe_bytes
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
@@ -23,7 +23,8 b' import vcsserver'
23 import tempfile
23 import tempfile
24 from vcsserver import hook_utils
24 from vcsserver import hook_utils
25 from vcsserver.tests.fixture import no_newline_id_generator
25 from vcsserver.tests.fixture import no_newline_id_generator
26 from vcsserver.utils import AttributeDict, safe_bytes, safe_str
26 from vcsserver.str_utils import safe_bytes, safe_str
27 from vcsserver.utils import AttributeDict
27
28
28
29
29 class TestCheckRhodecodeHook(object):
30 class TestCheckRhodecodeHook(object):
@@ -26,8 +26,7 b' import webtest'
26
26
27 from vcsserver import hooks, pygrack
27 from vcsserver import hooks, pygrack
28
28
29 # pylint: disable=redefined-outer-name,protected-access
29 from vcsserver.str_utils import ascii_bytes
30 from vcsserver.utils import ascii_bytes
31
30
32
31
33 @pytest.fixture()
32 @pytest.fixture()
@@ -25,7 +25,7 b' import pytest'
25 import webtest
25 import webtest
26
26
27 from vcsserver import scm_app
27 from vcsserver import scm_app
28 from vcsserver.utils import ascii_bytes
28 from vcsserver.str_utils import ascii_bytes
29
29
30
30
31 def test_hg_does_not_accept_invalid_cmd(tmpdir):
31 def test_hg_does_not_accept_invalid_cmd(tmpdir):
@@ -22,7 +22,7 b' import sys'
22 import pytest
22 import pytest
23
23
24 from vcsserver import subprocessio
24 from vcsserver import subprocessio
25 from vcsserver.utils import ascii_bytes
25 from vcsserver.str_utils import ascii_bytes
26
26
27
27
28 class FileLikeObj(object): # pragma: no cover
28 class FileLikeObj(object): # pragma: no cover
@@ -20,7 +20,7 b' import mock'
20 import pytest
20 import pytest
21 import sys
21 import sys
22
22
23 from vcsserver.utils import ascii_bytes
23 from vcsserver.str_utils import ascii_bytes
24
24
25
25
26 class MockPopen(object):
26 class MockPopen(object):
@@ -16,7 +16,7 b''
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import pytest
18 import pytest
19 from vcsserver.utils import ascii_bytes, ascii_str
19 from vcsserver.str_utils import ascii_bytes, ascii_str
20
20
21
21
22 @pytest.mark.parametrize('given, expected', [
22 @pytest.mark.parametrize('given, expected', [
@@ -19,7 +19,7 b' import wsgiref.simple_server'
19 import wsgiref.validate
19 import wsgiref.validate
20
20
21 from vcsserver import wsgi_app_caller
21 from vcsserver import wsgi_app_caller
22 from vcsserver.utils import ascii_bytes, safe_str
22 from vcsserver.str_utils import ascii_bytes, safe_str
23
23
24
24
25 @wsgiref.validate.validator
25 @wsgiref.validate.validator
@@ -19,7 +19,7 b' import time'
19 import logging
19 import logging
20
20
21 import vcsserver
21 import vcsserver
22 from vcsserver.utils import safe_str, ascii_str
22 from vcsserver.str_utils import safe_str, ascii_str
23
23
24 log = logging.getLogger(__name__)
24 log = logging.getLogger(__name__)
25
25
@@ -20,118 +20,35 b' import hashlib'
20 log = logging.getLogger(__name__)
20 log = logging.getLogger(__name__)
21
21
22
22
23 def safe_int(val, default=None):
23 class AttributeDictBase(dict):
24 """
24 def __getstate__(self):
25 Returns int() of val if val is not convertable to int use default
25 odict = self.__dict__ # get attribute dictionary
26 instead
26 return odict
27
28 :param val:
29 :param default:
30 """
31
32 try:
33 val = int(val)
34 except (ValueError, TypeError):
35 val = default
36
37 return val
38
39
40 def safe_str(str_, to_encoding=None) -> str:
41 """
42 safe str function. Does few trick to turn unicode_ into string
43
44 :param str_: str to encode
45 :param to_encoding: encode to this type UTF8 default
46 :rtype: str
47 :returns: str object
48 """
49 if isinstance(str_, str):
50 return str_
51
52 # if it's bytes cast to str
53 if not isinstance(str_, bytes):
54 return str(str_)
55
56 to_encoding = to_encoding or ['utf8']
57 if not isinstance(to_encoding, (list, tuple)):
58 to_encoding = [to_encoding]
59
60 for enc in to_encoding:
61 try:
62 return str(str_, enc)
63 except UnicodeDecodeError:
64 pass
65
66 return str(str_, to_encoding[0], 'replace')
67
68
69 def safe_bytes(str_, from_encoding=None) -> bytes:
70 """
71 safe bytes function. Does few trick to turn str_ into bytes string:
72
27
73 :param str_: string to decode
28 def __setstate__(self, dict):
74 :param from_encoding: encode from this type UTF8 default
29 self.__dict__ = dict
75 :rtype: unicode
76 :returns: unicode object
77 """
78 if isinstance(str_, bytes):
79 return str_
80
81 if not isinstance(str_, str):
82 raise ValueError('safe_bytes cannot convert other types than str: got: {}'.format(type(str_)))
83
84 from_encoding = from_encoding or ['utf8']
85 if not isinstance(from_encoding, (list, tuple)):
86 from_encoding = [from_encoding]
87
88 for enc in from_encoding:
89 try:
90 return str_.encode(enc)
91 except UnicodeDecodeError:
92 pass
93
94 return str_.encode(from_encoding[0], 'replace')
95
96
30
97 def ascii_bytes(str_, allow_bytes=False) -> bytes:
98 """
99 Simple conversion from str to bytes, with assumption that str_ is pure ASCII.
100 Fails with UnicodeError on invalid input.
101 This should be used where encoding and "safe" ambiguity should be avoided.
102 Where strings already have been encoded in other ways but still are unicode
103 string - for example to hex, base64, json, urlencoding, or are known to be
104 identifiers.
105 """
106 if allow_bytes and isinstance(str_, bytes):
107 return str_
108
109 if not isinstance(str_, str):
110 raise ValueError('ascii_bytes cannot convert other types than str: got: {}'.format(type(str_)))
111 return str_.encode('ascii')
112
113
114 def ascii_str(str_):
115 """
116 Simple conversion from bytes to str, with assumption that str_ is pure ASCII.
117 Fails with UnicodeError on invalid input.
118 This should be used where encoding and "safe" ambiguity should be avoided.
119 Where strings are encoded but also in other ways are known to be ASCII, and
120 where a unicode string is wanted without caring about encoding. For example
121 to hex, base64, urlencoding, or are known to be identifiers.
122 """
123
124 if not isinstance(str_, bytes):
125 raise ValueError('ascii_str cannot convert other types than bytes: got: {}'.format(type(str_)))
126 return str_.decode('ascii')
127
128
129 class AttributeDict(dict):
130 def __getattr__(self, attr):
131 return self.get(attr, None)
132 __setattr__ = dict.__setitem__
31 __setattr__ = dict.__setitem__
133 __delattr__ = dict.__delitem__
32 __delattr__ = dict.__delitem__
134
33
135
34
35 class StrictAttributeDict(AttributeDictBase):
36 """
37 Strict Version of Attribute dict which raises an Attribute error when
38 requested attribute is not set
39 """
40 def __getattr__(self, attr):
41 try:
42 return self[attr]
43 except KeyError:
44 raise AttributeError('%s object has no attribute %s' % (
45 self.__class__, attr))
46
47
48 class AttributeDict(AttributeDictBase):
49 def __getattr__(self, attr):
50 return self.get(attr, None)
51
52
136 def sha1(val):
53 def sha1(val):
137 return hashlib.sha1(val).hexdigest()
54 return hashlib.sha1(val).hexdigest()
@@ -23,7 +23,7 b' import io'
23 import logging
23 import logging
24 import os
24 import os
25
25
26 from vcsserver.utils import ascii_bytes
26 from vcsserver.str_utils import ascii_bytes
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29
29
General Comments 0
You need to be logged in to leave comments. Login now