{"action":"opened","number":676,"pull_request":{"url":"https://api.github.com/repos/Pyomo/pyomo/pulls/676","id":212517706,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEyNTE3NzA2","html_url":"https://github.com/Pyomo/pyomo/pull/676","diff_url":"https://github.com/Pyomo/pyomo/pull/676.diff","patch_url":"https://github.com/Pyomo/pyomo/pull/676.patch","issue_url":"https://api.github.com/repos/Pyomo/pyomo/issues/676","number":676,"state":"open","locked":false,"title":"Adding files that define pyomo.ext","user":{"login":"whart222","id":728056,"node_id":"MDQ6VXNlcjcyODA1Ng==","avatar_url":"https://avatars2.githubusercontent.com/u/728056?v=4","gravatar_id":"","url":"https://api.github.com/users/whart222","html_url":"https://github.com/whart222","followers_url":"https://api.github.com/users/whart222/followers","following_url":"https://api.github.com/users/whart222/following{/other_user}","gists_url":"https://api.github.com/users/whart222/gists{/gist_id}","starred_url":"https://api.github.com/users/whart222/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whart222/subscriptions","organizations_url":"https://api.github.com/users/whart222/orgs","repos_url":"https://api.github.com/users/whart222/repos","events_url":"https://api.github.com/users/whart222/events{/privacy}","received_events_url":"https://api.github.com/users/whart222/received_events","type":"User","site_admin":false},"body":"## Fixes NA.\r\n\r\n## Summary/Motivation:\r\n\r\n### Overview\r\n\r\nThis PR is a proof-of-concept for creating a dynamic pyomo.ext module.  The idea is that when a user/developer executes\r\n```\r\nimport pyomo.ext.foo\r\n```\r\nthen the symbols from the package \"pyomoext_foo\" are imported below \"ext\".  If pyomo.ext had an __init__.py file, then this would be equivalent to the following line being added to the that file:\r\n```\r\nimport pyomoext_foo as foo\r\n```\r\n\r\nThis is similar to pyomo.contrib, in that users/developers can pull-in external packages that look like they are part of pyomo.  The key difference is that the pyomo.ext module does this dynamically.  Thus, no previous registration is required.  All packages that begin with \"pyomoext_\" can be imported dynamically.\r\n\r\nAdditionally, the pyomo/__init__.py defines a dictionary that is used to initialize pyomo.ext, which can specify additional extension packages that do not follow this naming convention.  This allows Pyomo to optionally standardize the use of external packages through pyomo.ext.\r\n\r\n### Motivation\r\n\r\nWhile Pyomo has been developed as a monolithic package, increasingly developers have made the distinction between (1) the \"core\" packages that define key elements of Pyomo's modeling environment and (2) \"extension\" packages that build on these \"core\" capabilities.  For example, Pyomo's expression system and file writers are core elements, which the GDP/PYSP/DAE modeling packages extend to represent different classes of optimization applications.\r\n\r\nFurther, developers are increasingly developing extensions of Pyomo that require a separate development repository.  For example, Pyomo extensions are being developed in private repositories to support and protect unpublished research activities.  Similarly, Pyomo extensions are being developed in separate repositories for low-TRL research activities;  such projects are often ill-suited for direct inclusion in Pyomo since they involve immature, unstable code.  (FUrther, I'd argue that Pyomo's peer-review development process is ill-suited for such projects.)\r\n\r\nWhile Pyomo development can proceed without coordination amongst such activities, this PR supports the definition of a common namespace that allows Pyomo and related packages to develop capabilities in a synergistic manner.  For example, if John is developing package foo, and he has a cool new function bar(), then my package can reliably import:\r\n```\r\nfrom pyomo.ext.foo import bar\r\n```\r\nSure, I don't need to do that, since\r\n```\r\nfrom foo import bar\r\n```\r\nalso works.  But the pyomo.ext module defines a namespace that minimizes the logical overhead for users/developers.  We can all act like we're working within a namespace, even if packages have different names.\r\n\r\n## Changes proposed in this PR:\r\n- This PR creates the pyomo.ext object, which is a module that dynamically translates the name of the package being imported.\r\n- The module object is created using the _ImportRedirect class, which defined in pyomo.common.ext.py\r\n\r\n### Legal Acknowledgement\r\n\r\nBy contributing to this software project, I agree to the following terms and conditions for my contribution:\r\n\r\n1. I agree my contributions are submitted under the BSD license.\r\n2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.\r\n","created_at":"2018-09-01T00:18:14Z","updated_at":"2018-09-01T00:18:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Pyomo/pyomo/pulls/676/commits","review_comments_url":"https://api.github.com/repos/Pyomo/pyomo/pulls/676/comments","review_comment_url":"https://api.github.com/repos/Pyomo/pyomo/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Pyomo/pyomo/issues/676/comments","statuses_url":"https://api.github.com/repos/Pyomo/pyomo/statuses/b2ed61542ba3d27c417f55553d5c27ae16a769ac","head":{"label":"Pyomo:pyomoext2","ref":"pyomoext2","sha":"b2ed61542ba3d27c417f55553d5c27ae16a769ac","user":{"login":"Pyomo","id":10505959,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNTA1OTU5","avatar_url":"https://avatars2.githubusercontent.com/u/10505959?v=4","gravatar_id":"","url":"https://api.github.com/users/Pyomo","html_url":"https://github.com/Pyomo","followers_url":"https://api.github.com/users/Pyomo/followers","following_url":"https://api.github.com/users/Pyomo/following{/other_user}","gists_url":"https://api.github.com/users/Pyomo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pyomo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pyomo/subscriptions","organizations_url":"https://api.github.com/users/Pyomo/orgs","repos_url":"https://api.github.com/users/Pyomo/repos","events_url":"https://api.github.com/users/Pyomo/events{/privacy}","received_events_url":"https://api.github.com/users/Pyomo/received_events","type":"Organization","site_admin":false},"repo":{"id":59858718,"node_id":"MDEwOlJlcG9zaXRvcnk1OTg1ODcxOA==","name":"pyomo","full_name":"Pyomo/pyomo","owner":{"login":"Pyomo","id":10505959,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNTA1OTU5","avatar_url":"https://avatars2.githubusercontent.com/u/10505959?v=4","gravatar_id":"","url":"https://api.github.com/users/Pyomo","html_url":"https://github.com/Pyomo","followers_url":"https://api.github.com/users/Pyomo/followers","following_url":"https://api.github.com/users/Pyomo/following{/other_user}","gists_url":"https://api.github.com/users/Pyomo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pyomo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pyomo/subscriptions","organizations_url":"https://api.github.com/users/Pyomo/orgs","repos_url":"https://api.github.com/users/Pyomo/repos","events_url":"https://api.github.com/users/Pyomo/events{/privacy}","received_events_url":"https://api.github.com/users/Pyomo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Pyomo/pyomo","description":"The main repository for the Pyomo optimization modeling software.","fork":false,"url":"https://api.github.com/repos/Pyomo/pyomo","forks_url":"https://api.github.com/repos/Pyomo/pyomo/forks","keys_url":"https://api.github.com/repos/Pyomo/pyomo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Pyomo/pyomo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Pyomo/pyomo/teams","hooks_url":"https://api.github.com/repos/Pyomo/pyomo/hooks","issue_events_url":"https://api.github.com/repos/Pyomo/pyomo/issues/events{/number}","events_url":"https://api.github.com/repos/Pyomo/pyomo/events","assignees_url":"https://api.github.com/repos/Pyomo/pyomo/assignees{/user}","branches_url":"https://api.github.com/repos/Pyomo/pyomo/branches{/branch}","tags_url":"https://api.github.com/repos/Pyomo/pyomo/tags","blobs_url":"https://api.github.com/repos/Pyomo/pyomo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Pyomo/pyomo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Pyomo/pyomo/git/refs{/sha}","trees_url":"https://api.github.com/repos/Pyomo/pyomo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Pyomo/pyomo/statuses/{sha}","languages_url":"https://api.github.com/repos/Pyomo/pyomo/languages","stargazers_url":"https://api.github.com/repos/Pyomo/pyomo/stargazers","contributors_url":"https://api.github.com/repos/Pyomo/pyomo/contributors","subscribers_url":"https://api.github.com/repos/Pyomo/pyomo/subscribers","subscription_url":"https://api.github.com/repos/Pyomo/pyomo/subscription","commits_url":"https://api.github.com/repos/Pyomo/pyomo/commits{/sha}","git_commits_url":"https://api.github.com/repos/Pyomo/pyomo/git/commits{/sha}","comments_url":"https://api.github.com/repos/Pyomo/pyomo/comments{/number}","issue_comment_url":"https://api.github.com/repos/Pyomo/pyomo/issues/comments{/number}","contents_url":"https://api.github.com/repos/Pyomo/pyomo/contents/{+path}","compare_url":"https://api.github.com/repos/Pyomo/pyomo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Pyomo/pyomo/merges","archive_url":"https://api.github.com/repos/Pyomo/pyomo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Pyomo/pyomo/downloads","issues_url":"https://api.github.com/repos/Pyomo/pyomo/issues{/number}","pulls_url":"https://api.github.com/repos/Pyomo/pyomo/pulls{/number}","milestones_url":"https://api.github.com/repos/Pyomo/pyomo/milestones{/number}","notifications_url":"https://api.github.com/repos/Pyomo/pyomo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Pyomo/pyomo/labels{/name}","releases_url":"https://api.github.com/repos/Pyomo/pyomo/releases{/id}","deployments_url":"https://api.github.com/repos/Pyomo/pyomo/deployments","created_at":"2016-05-27T19:33:45Z","updated_at":"2018-08-28T06:20:52Z","pushed_at":"2018-09-01T00:16:56Z","git_url":"git://github.com/Pyomo/pyomo.git","ssh_url":"git@github.com:Pyomo/pyomo.git","clone_url":"https://github.com/Pyomo/pyomo.git","svn_url":"https://github.com/Pyomo/pyomo","homepage":null,"size":41611,"stargazers_count":296,"watchers_count":296,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":116,"mirror_url":null,"archived":false,"open_issues_count":196,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":116,"open_issues":196,"watchers":296,"default_branch":"master"}},"base":{"label":"Pyomo:master","ref":"master","sha":"8be17fd8772450c1c15ddc93b196e023af1de36d","user":{"login":"Pyomo","id":10505959,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNTA1OTU5","avatar_url":"https://avatars2.githubusercontent.com/u/10505959?v=4","gravatar_id":"","url":"https://api.github.com/users/Pyomo","html_url":"https://github.com/Pyomo","followers_url":"https://api.github.com/users/Pyomo/followers","following_url":"https://api.github.com/users/Pyomo/following{/other_user}","gists_url":"https://api.github.com/users/Pyomo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pyomo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pyomo/subscriptions","organizations_url":"https://api.github.com/users/Pyomo/orgs","repos_url":"https://api.github.com/users/Pyomo/repos","events_url":"https://api.github.com/users/Pyomo/events{/privacy}","received_events_url":"https://api.github.com/users/Pyomo/received_events","type":"Organization","site_admin":false},"repo":{"id":59858718,"node_id":"MDEwOlJlcG9zaXRvcnk1OTg1ODcxOA==","name":"pyomo","full_name":"Pyomo/pyomo","owner":{"login":"Pyomo","id":10505959,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNTA1OTU5","avatar_url":"https://avatars2.githubusercontent.com/u/10505959?v=4","gravatar_id":"","url":"https://api.github.com/users/Pyomo","html_url":"https://github.com/Pyomo","followers_url":"https://api.github.com/users/Pyomo/followers","following_url":"https://api.github.com/users/Pyomo/following{/other_user}","gists_url":"https://api.github.com/users/Pyomo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pyomo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pyomo/subscriptions","organizations_url":"https://api.github.com/users/Pyomo/orgs","repos_url":"https://api.github.com/users/Pyomo/repos","events_url":"https://api.github.com/users/Pyomo/events{/privacy}","received_events_url":"https://api.github.com/users/Pyomo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Pyomo/pyomo","description":"The main repository for the Pyomo optimization modeling software.","fork":false,"url":"https://api.github.com/repos/Pyomo/pyomo","forks_url":"https://api.github.com/repos/Pyomo/pyomo/forks","keys_url":"https://api.github.com/repos/Pyomo/pyomo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Pyomo/pyomo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Pyomo/pyomo/teams","hooks_url":"https://api.github.com/repos/Pyomo/pyomo/hooks","issue_events_url":"https://api.github.com/repos/Pyomo/pyomo/issues/events{/number}","events_url":"https://api.github.com/repos/Pyomo/pyomo/events","assignees_url":"https://api.github.com/repos/Pyomo/pyomo/assignees{/user}","branches_url":"https://api.github.com/repos/Pyomo/pyomo/branches{/branch}","tags_url":"https://api.github.com/repos/Pyomo/pyomo/tags","blobs_url":"https://api.github.com/repos/Pyomo/pyomo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Pyomo/pyomo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Pyomo/pyomo/git/refs{/sha}","trees_url":"https://api.github.com/repos/Pyomo/pyomo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Pyomo/pyomo/statuses/{sha}","languages_url":"https://api.github.com/repos/Pyomo/pyomo/languages","stargazers_url":"https://api.github.com/repos/Pyomo/pyomo/stargazers","contributors_url":"https://api.github.com/repos/Pyomo/pyomo/contributors","subscribers_url":"https://api.github.com/repos/Pyomo/pyomo/subscribers","subscription_url":"https://api.github.com/repos/Pyomo/pyomo/subscription","commits_url":"https://api.github.com/repos/Pyomo/pyomo/commits{/sha}","git_commits_url":"https://api.github.com/repos/Pyomo/pyomo/git/commits{/sha}","comments_url":"https://api.github.com/repos/Pyomo/pyomo/comments{/number}","issue_comment_url":"https://api.github.com/repos/Pyomo/pyomo/issues/comments{/number}","contents_url":"https://api.github.com/repos/Pyomo/pyomo/contents/{+path}","compare_url":"https://api.github.com/repos/Pyomo/pyomo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Pyomo/pyomo/merges","archive_url":"https://api.github.com/repos/Pyomo/pyomo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Pyomo/pyomo/downloads","issues_url":"https://api.github.com/repos/Pyomo/pyomo/issues{/number}","pulls_url":"https://api.github.com/repos/Pyomo/pyomo/pulls{/number}","milestones_url":"https://api.github.com/repos/Pyomo/pyomo/milestones{/number}","notifications_url":"https://api.github.com/repos/Pyomo/pyomo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Pyomo/pyomo/labels{/name}","releases_url":"https://api.github.com/repos/Pyomo/pyomo/releases{/id}","deployments_url":"https://api.github.com/repos/Pyomo/pyomo/deployments","created_at":"2016-05-27T19:33:45Z","updated_at":"2018-08-28T06:20:52Z","pushed_at":"2018-09-01T00:16:56Z","git_url":"git://github.com/Pyomo/pyomo.git","ssh_url":"git@github.com:Pyomo/pyomo.git","clone_url":"https://github.com/Pyomo/pyomo.git","svn_url":"https://github.com/Pyomo/pyomo","homepage":null,"size":41611,"stargazers_count":296,"watchers_count":296,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":116,"mirror_url":null,"archived":false,"open_issues_count":196,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":116,"open_issues":196,"watchers":296,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Pyomo/pyomo/pulls/676"},"html":{"href":"https://github.com/Pyomo/pyomo/pull/676"},"issue":{"href":"https://api.github.com/repos/Pyomo/pyomo/issues/676"},"comments":{"href":"https://api.github.com/repos/Pyomo/pyomo/issues/676/comments"},"review_comments":{"href":"https://api.github.com/repos/Pyomo/pyomo/pulls/676/comments"},"review_comment":{"href":"https://api.github.com/repos/Pyomo/pyomo/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Pyomo/pyomo/pulls/676/commits"},"statuses":{"href":"https://api.github.com/repos/Pyomo/pyomo/statuses/b2ed61542ba3d27c417f55553d5c27ae16a769ac"}},"author_association":"MEMBER","merged":false,"mergeable":null,"rebaseable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"maintainer_can_modify":false,"commits":1,"additions":109,"deletions":0,"changed_files":2}}
{"actor":{"display_login":"whart222"}}