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 |
|
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 |
|
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() |
General Comments 0
You need to be logged in to leave comments.
Login now