{"action":"created","comment":{"url":"https://api.github.com/repos/artefactual/archivematica/pulls/comments/46895563","id":46895563,"diff_hunk":"@@ -0,0 +1,73 @@\n+import os\n+import ConfigParser\n+import functools\n+\n+\n+def fallback_option(fn):\n+    def wrapper(*args, **kwargs):\n+        fallback = kwargs.pop('fallback', None)\n+        try:\n+            return fn(*args, **kwargs)\n+        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):\n+            if fallback:\n+                return fallback\n+            raise\n+    return functools.wraps(fn)(wrapper)\n+\n+\n+class EnvConfigParser(ConfigParser.SafeConfigParser):\n+    \"\"\"\n+    EnvConfigParser enables the user to provide configuration defaults using\n+    the string environment, e.g. given:\n+\n+      - String environment prefix (prefix) = \"ARCHIVEMATICA_MCPSERVER\"\n+      - Configuration section: \"network\"\n+      - Configuration option: \"tls\"\n+\n+    This parser will first try to find the configuration value in the string\n+    environment matching one of the two following keys:\n+\n+      - ARCHIVEMATICA_MCPSERVER_NETWORK_TLS\n+      - ARCHIVEMATICA_MCPSERVER_TLS\n+\n+    It the variable is not set in the string environment the reader falls back\n+    on the main configuration backend.\n+\n+    Additionally, the getters (get(), getint(), etc...) accept a new parameter\n+    (fallback) that returns the value given to it instead of an exception when\n+    the section or option trying to be match are undefined.\n+    \"\"\"\n+    ENVVAR_SEPARATOR = '_'\n+\n+    def __init__(self, defaults=None, env=None, prefix=''):\n+        self._environ = os.environ if env is None else env\n+        self._prefix = prefix.rstrip('_')\n+        ConfigParser.SafeConfigParser.__init__(self, defaults)","path":"src/archivematicaCommon/lib/env_configparser.py","position":45,"original_position":45,"commit_id":"5f9d918fc3b2a2e621b27413a094e487ea121e46","original_commit_id":"5f9d918fc3b2a2e621b27413a094e487ea121e46","user":{"login":"Hwesta","id":3166226,"avatar_url":"https://avatars.githubusercontent.com/u/3166226?v=3","gravatar_id":"","url":"https://api.github.com/users/Hwesta","html_url":"https://github.com/Hwesta","followers_url":"https://api.github.com/users/Hwesta/followers","following_url":"https://api.github.com/users/Hwesta/following{/other_user}","gists_url":"https://api.github.com/users/Hwesta/gists{/gist_id}","starred_url":"https://api.github.com/users/Hwesta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hwesta/subscriptions","organizations_url":"https://api.github.com/users/Hwesta/orgs","repos_url":"https://api.github.com/users/Hwesta/repos","events_url":"https://api.github.com/users/Hwesta/events{/privacy}","received_events_url":"https://api.github.com/users/Hwesta/received_events","type":"User","site_admin":false},"body":"Ah, I didn't realize py2 configparser didn't subclass `object`. :(  We don't have a policy now, but I suspect we'll be supporting both, at least initially.  Not worth fixing now though if it's significant effort.","created_at":"2015-12-07T23:38:07Z","updated_at":"2015-12-07T23:38:07Z","html_url":"https://github.com/artefactual/archivematica/pull/351#discussion_r46895563","pull_request_url":"https://api.github.com/repos/artefactual/archivematica/pulls/351","_links":{"self":{"href":"https://api.github.com/repos/artefactual/archivematica/pulls/comments/46895563"},"html":{"href":"https://github.com/artefactual/archivematica/pull/351#discussion_r46895563"},"pull_request":{"href":"https://api.github.com/repos/artefactual/archivematica/pulls/351"}}},"pull_request":{"url":"https://api.github.com/repos/artefactual/archivematica/pulls/351","id":52884763,"html_url":"https://github.com/artefactual/archivematica/pull/351","diff_url":"https://github.com/artefactual/archivematica/pull/351.diff","patch_url":"https://github.com/artefactual/archivematica/pull/351.patch","issue_url":"https://api.github.com/repos/artefactual/archivematica/issues/351","number":351,"state":"open","locked":false,"title":"Add EnvConfigParser subclass with environment string support","user":{"login":"sevein","id":606459,"avatar_url":"https://avatars.githubusercontent.com/u/606459?v=3","gravatar_id":"","url":"https://api.github.com/users/sevein","html_url":"https://github.com/sevein","followers_url":"https://api.github.com/users/sevein/followers","following_url":"https://api.github.com/users/sevein/following{/other_user}","gists_url":"https://api.github.com/users/sevein/gists{/gist_id}","starred_url":"https://api.github.com/users/sevein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sevein/subscriptions","organizations_url":"https://api.github.com/users/sevein/orgs","repos_url":"https://api.github.com/users/sevein/repos","events_url":"https://api.github.com/users/sevein/events{/privacy}","received_events_url":"https://api.github.com/users/sevein/received_events","type":"User","site_admin":false},"body":"Planning to use `EnvConfigParser` in the future. Let me know what you think!\r\n\r\n---\r\n\r\nMain two differences comparing it to its ancestor `SafeConfigParser` are:\r\n\r\n- The settings are looked up first in the string environment, trying to match\r\n  both `section` and `option` first and only `option` as a fallback, e.g.\r\n  `ARCHIVEMATICA_SECTION_OPTION` and `ARCHIVEMATICA_OPTION`.\r\n- All the getters (`get`, `getint`, `getfloat`, `getbool`) learn a new keyword\r\n  argument `fallback` so its value is returned when the configuration option\r\n  is undefined, instead of throwing exceptions like `NoSectionError` or\r\n  `NoOptionError`, as with a Python dictionary. This mimics the behavior\r\n  introduced in the `configparser` module in Python 3. For example, you could\r\n  write:\r\n\r\n      tls_enabled = config.getboolean('network', 'tls', fallback=False)\r\n\r\n  instead of:\r\n\r\n      try:\r\n          tls_enabled = config.getboolean('network', 'tls')\r\n      except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):\r\n          tls_enabled = False","created_at":"2015-12-07T18:52:55Z","updated_at":"2015-12-07T23:38:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"294c4e0666bda7b186f62e70f842c121c7432fbc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/artefactual/archivematica/pulls/351/commits","review_comments_url":"https://api.github.com/repos/artefactual/archivematica/pulls/351/comments","review_comment_url":"https://api.github.com/repos/artefactual/archivematica/pulls/comments{/number}","comments_url":"https://api.github.com/repos/artefactual/archivematica/issues/351/comments","statuses_url":"https://api.github.com/repos/artefactual/archivematica/statuses/5f9d918fc3b2a2e621b27413a094e487ea121e46","head":{"label":"artefactual:dev/environ-config-parser","ref":"dev/environ-config-parser","sha":"5f9d918fc3b2a2e621b27413a094e487ea121e46","user":{"login":"artefactual","id":1163545,"avatar_url":"https://avatars.githubusercontent.com/u/1163545?v=3","gravatar_id":"","url":"https://api.github.com/users/artefactual","html_url":"https://github.com/artefactual","followers_url":"https://api.github.com/users/artefactual/followers","following_url":"https://api.github.com/users/artefactual/following{/other_user}","gists_url":"https://api.github.com/users/artefactual/gists{/gist_id}","starred_url":"https://api.github.com/users/artefactual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/artefactual/subscriptions","organizations_url":"https://api.github.com/users/artefactual/orgs","repos_url":"https://api.github.com/users/artefactual/repos","events_url":"https://api.github.com/users/artefactual/events{/privacy}","received_events_url":"https://api.github.com/users/artefactual/received_events","type":"Organization","site_admin":false},"repo":{"id":5811958,"name":"archivematica","full_name":"artefactual/archivematica","owner":{"login":"artefactual","id":1163545,"avatar_url":"https://avatars.githubusercontent.com/u/1163545?v=3","gravatar_id":"","url":"https://api.github.com/users/artefactual","html_url":"https://github.com/artefactual","followers_url":"https://api.github.com/users/artefactual/followers","following_url":"https://api.github.com/users/artefactual/following{/other_user}","gists_url":"https://api.github.com/users/artefactual/gists{/gist_id}","starred_url":"https://api.github.com/users/artefactual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/artefactual/subscriptions","organizations_url":"https://api.github.com/users/artefactual/orgs","repos_url":"https://api.github.com/users/artefactual/repos","events_url":"https://api.github.com/users/artefactual/events{/privacy}","received_events_url":"https://api.github.com/users/artefactual/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/artefactual/archivematica","description":"Free and open-source digital preservation system designed to maintain standards-based, long-term access to collections of digital objects.","fork":false,"url":"https://api.github.com/repos/artefactual/archivematica","forks_url":"https://api.github.com/repos/artefactual/archivematica/forks","keys_url":"https://api.github.com/repos/artefactual/archivematica/keys{/key_id}","collaborators_url":"https://api.github.com/repos/artefactual/archivematica/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/artefactual/archivematica/teams","hooks_url":"https://api.github.com/repos/artefactual/archivematica/hooks","issue_events_url":"https://api.github.com/repos/artefactual/archivematica/issues/events{/number}","events_url":"https://api.github.com/repos/artefactual/archivematica/events","assignees_url":"https://api.github.com/repos/artefactual/archivematica/assignees{/user}","branches_url":"https://api.github.com/repos/artefactual/archivematica/branches{/branch}","tags_url":"https://api.github.com/repos/artefactual/archivematica/tags","blobs_url":"https://api.github.com/repos/artefactual/archivematica/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/artefactual/archivematica/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/artefactual/archivematica/git/refs{/sha}","trees_url":"https://api.github.com/repos/artefactual/archivematica/git/trees{/sha}","statuses_url":"https://api.github.com/repos/artefactual/archivematica/statuses/{sha}","languages_url":"https://api.github.com/repos/artefactual/archivematica/languages","stargazers_url":"https://api.github.com/repos/artefactual/archivematica/stargazers","contributors_url":"https://api.github.com/repos/artefactual/archivematica/contributors","subscribers_url":"https://api.github.com/repos/artefactual/archivematica/subscribers","subscription_url":"https://api.github.com/repos/artefactual/archivematica/subscription","commits_url":"https://api.github.com/repos/artefactual/archivematica/commits{/sha}","git_commits_url":"https://api.github.com/repos/artefactual/archivematica/git/commits{/sha}","comments_url":"https://api.github.com/repos/artefactual/archivematica/comments{/number}","issue_comment_url":"https://api.github.com/repos/artefactual/archivematica/issues/comments{/number}","contents_url":"https://api.github.com/repos/artefactual/archivematica/contents/{+path}","compare_url":"https://api.github.com/repos/artefactual/archivematica/compare/{base}...{head}","merges_url":"https://api.github.com/repos/artefactual/archivematica/merges","archive_url":"https://api.github.com/repos/artefactual/archivematica/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/artefactual/archivematica/downloads","issues_url":"https://api.github.com/repos/artefactual/archivematica/issues{/number}","pulls_url":"https://api.github.com/repos/artefactual/archivematica/pulls{/number}","milestones_url":"https://api.github.com/repos/artefactual/archivematica/milestones{/number}","notifications_url":"https://api.github.com/repos/artefactual/archivematica/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/artefactual/archivematica/labels{/name}","releases_url":"https://api.github.com/repos/artefactual/archivematica/releases{/id}","created_at":"2012-09-14T16:43:38Z","updated_at":"2015-12-07T16:18:21Z","pushed_at":"2015-12-07T23:26:05Z","git_url":"git://github.com/artefactual/archivematica.git","ssh_url":"git@github.com:artefactual/archivematica.git","clone_url":"https://github.com/artefactual/archivematica.git","svn_url":"https://github.com/artefactual/archivematica","homepage":"http://www.archivematica.org","size":26071,"stargazers_count":80,"watchers_count":80,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":20,"mirror_url":null,"open_issues_count":26,"forks":20,"open_issues":26,"watchers":80,"default_branch":"stable/1.4.x"}},"base":{"label":"artefactual:qa/1.x","ref":"qa/1.x","sha":"7c3ef4f448daa90aed8ef2087defe7e1fe78508d","user":{"login":"artefactual","id":1163545,"avatar_url":"https://avatars.githubusercontent.com/u/1163545?v=3","gravatar_id":"","url":"https://api.github.com/users/artefactual","html_url":"https://github.com/artefactual","followers_url":"https://api.github.com/users/artefactual/followers","following_url":"https://api.github.com/users/artefactual/following{/other_user}","gists_url":"https://api.github.com/users/artefactual/gists{/gist_id}","starred_url":"https://api.github.com/users/artefactual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/artefactual/subscriptions","organizations_url":"https://api.github.com/users/artefactual/orgs","repos_url":"https://api.github.com/users/artefactual/repos","events_url":"https://api.github.com/users/artefactual/events{/privacy}","received_events_url":"https://api.github.com/users/artefactual/received_events","type":"Organization","site_admin":false},"repo":{"id":5811958,"name":"archivematica","full_name":"artefactual/archivematica","owner":{"login":"artefactual","id":1163545,"avatar_url":"https://avatars.githubusercontent.com/u/1163545?v=3","gravatar_id":"","url":"https://api.github.com/users/artefactual","html_url":"https://github.com/artefactual","followers_url":"https://api.github.com/users/artefactual/followers","following_url":"https://api.github.com/users/artefactual/following{/other_user}","gists_url":"https://api.github.com/users/artefactual/gists{/gist_id}","starred_url":"https://api.github.com/users/artefactual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/artefactual/subscriptions","organizations_url":"https://api.github.com/users/artefactual/orgs","repos_url":"https://api.github.com/users/artefactual/repos","events_url":"https://api.github.com/users/artefactual/events{/privacy}","received_events_url":"https://api.github.com/users/artefactual/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/artefactual/archivematica","description":"Free and open-source digital preservation system designed to maintain standards-based, long-term access to collections of digital objects.","fork":false,"url":"https://api.github.com/repos/artefactual/archivematica","forks_url":"https://api.github.com/repos/artefactual/archivematica/forks","keys_url":"https://api.github.com/repos/artefactual/archivematica/keys{/key_id}","collaborators_url":"https://api.github.com/repos/artefactual/archivematica/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/artefactual/archivematica/teams","hooks_url":"https://api.github.com/repos/artefactual/archivematica/hooks","issue_events_url":"https://api.github.com/repos/artefactual/archivematica/issues/events{/number}","events_url":"https://api.github.com/repos/artefactual/archivematica/events","assignees_url":"https://api.github.com/repos/artefactual/archivematica/assignees{/user}","branches_url":"https://api.github.com/repos/artefactual/archivematica/branches{/branch}","tags_url":"https://api.github.com/repos/artefactual/archivematica/tags","blobs_url":"https://api.github.com/repos/artefactual/archivematica/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/artefactual/archivematica/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/artefactual/archivematica/git/refs{/sha}","trees_url":"https://api.github.com/repos/artefactual/archivematica/git/trees{/sha}","statuses_url":"https://api.github.com/repos/artefactual/archivematica/statuses/{sha}","languages_url":"https://api.github.com/repos/artefactual/archivematica/languages","stargazers_url":"https://api.github.com/repos/artefactual/archivematica/stargazers","contributors_url":"https://api.github.com/repos/artefactual/archivematica/contributors","subscribers_url":"https://api.github.com/repos/artefactual/archivematica/subscribers","subscription_url":"https://api.github.com/repos/artefactual/archivematica/subscription","commits_url":"https://api.github.com/repos/artefactual/archivematica/commits{/sha}","git_commits_url":"https://api.github.com/repos/artefactual/archivematica/git/commits{/sha}","comments_url":"https://api.github.com/repos/artefactual/archivematica/comments{/number}","issue_comment_url":"https://api.github.com/repos/artefactual/archivematica/issues/comments{/number}","contents_url":"https://api.github.com/repos/artefactual/archivematica/contents/{+path}","compare_url":"https://api.github.com/repos/artefactual/archivematica/compare/{base}...{head}","merges_url":"https://api.github.com/repos/artefactual/archivematica/merges","archive_url":"https://api.github.com/repos/artefactual/archivematica/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/artefactual/archivematica/downloads","issues_url":"https://api.github.com/repos/artefactual/archivematica/issues{/number}","pulls_url":"https://api.github.com/repos/artefactual/archivematica/pulls{/number}","milestones_url":"https://api.github.com/repos/artefactual/archivematica/milestones{/number}","notifications_url":"https://api.github.com/repos/artefactual/archivematica/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/artefactual/archivematica/labels{/name}","releases_url":"https://api.github.com/repos/artefactual/archivematica/releases{/id}","created_at":"2012-09-14T16:43:38Z","updated_at":"2015-12-07T16:18:21Z","pushed_at":"2015-12-07T23:26:05Z","git_url":"git://github.com/artefactual/archivematica.git","ssh_url":"git@github.com:artefactual/archivematica.git","clone_url":"https://github.com/artefactual/archivematica.git","svn_url":"https://github.com/artefactual/archivematica","homepage":"http://www.archivematica.org","size":26071,"stargazers_count":80,"watchers_count":80,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":20,"mirror_url":null,"open_issues_count":26,"forks":20,"open_issues":26,"watchers":80,"default_branch":"stable/1.4.x"}},"_links":{"self":{"href":"https://api.github.com/repos/artefactual/archivematica/pulls/351"},"html":{"href":"https://github.com/artefactual/archivematica/pull/351"},"issue":{"href":"https://api.github.com/repos/artefactual/archivematica/issues/351"},"comments":{"href":"https://api.github.com/repos/artefactual/archivematica/issues/351/comments"},"review_comments":{"href":"https://api.github.com/repos/artefactual/archivematica/pulls/351/comments"},"review_comment":{"href":"https://api.github.com/repos/artefactual/archivematica/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/artefactual/archivematica/pulls/351/commits"},"statuses":{"href":"https://api.github.com/repos/artefactual/archivematica/statuses/5f9d918fc3b2a2e621b27413a094e487ea121e46"}}}}