Platform independent whereis functionMultipurpose command-line utility to manage a web applicationANSI colors...
Recrystallisation of dibenzylideneacetone
What is the wife of a henpecked husband called?
If turtles see everything, and nothing seen can see, does it follow that non-turtles exist?
Why did other German political parties disband so fast when Hitler was appointed chancellor?
Why would the Pakistan airspace closure cancel flights not headed to Pakistan itself?
Can a dragon be stuck looking like a human?
Groups acting on trees
Why zero tolerance on nudity in space?
Using only 1s, make 29 with the minimum number of digits
Early credit roll before the end of the film
What is the purpose of easy combat scenarios that don't need resource expenditure?
Quenching swords in dragon blood; why?
Is there any differences between "Gucken" and "Schauen"?
Can I write a book of my D&D game?
Placing an adverb between a verb and an object?
Is it a fallacy if someone claims they need an explanation for every word of your argument to the point where they don't understand common terms?
Strange Sign on Lab Door
What makes the Forgotten Realms "forgotten"?
Check if the digits in the number are in increasing sequence in python
Why is working on the same position for more than 15 years not a red flag?
Every character has a name - does this lead to too many named characters?
What to do if authors don't respond to my serious concerns about their paper?
How to deal with an incendiary email that was recalled
Can we use the stored gravitational potential energy of a building to produce power?
Platform independent whereis function
Multipurpose command-line utility to manage a web applicationANSI colors cross platformPlugin Pattern for Generic Python ApplicationCyther: The Cross Platform Cython/Python CompilerCross-platform file hash sum generator in PythonStreaming H264 video from PiCamera to a JavaFX ImageViewImproved version of “Let's read a random Goodreads book…”Optimize platform independent GetTickCount()Launcher for python.exe within a self-contained application packageCross-platform MySQL database backup using mysqldump
$begingroup$
I'm trying to write a platform independent Python (>=3.6.5) package that has a handful of java .class files that need to compiled using javac and run using java. This is simple enough task but I need to know if user has these installed already and the location of the executable assuming that neither of them is on the system path. That way I can just call the executable by it's path using subprocess.run. Which bring me to the subject of this review a platform independent whereis command.
import os, subprocess
from subprocess import CalledProcessError
def whereis(app):
"""Return a list of locations a given application.
Relies on the `where` system command in Windows and the `whereis` command in Unix.
Parameters
----------
app : str
Can be any application on the system path e.g. java.
Returns
-------
result : list
A list of locations where applications is installed.
Useage
------
>>>whereis('javac')
'C:\Program Files\Java\jdk1.8.0_162\bin\javac.exe'
"""
result = None
if os.name == "nt":# Windows
try:
result = subprocess.check_output("where {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not forund.",err)
else:# Unix
try:
result = subprocess.check_output("whereis {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
print("")
result = []
return result
else:
result = result.decode().replace("r", "").split("n")
result = list(filter(lambda x: len(x)>0, result))
return result
Questions
- Is there a standard library function that already covers this? I couldn't find one but that doesn't mean anything.
- Are there any caveats or edge cases that I'm missing?
- Can any general improvements be made to the code or docstring?
python python-3.x windows unix
$endgroup$
add a comment |
$begingroup$
I'm trying to write a platform independent Python (>=3.6.5) package that has a handful of java .class files that need to compiled using javac and run using java. This is simple enough task but I need to know if user has these installed already and the location of the executable assuming that neither of them is on the system path. That way I can just call the executable by it's path using subprocess.run. Which bring me to the subject of this review a platform independent whereis command.
import os, subprocess
from subprocess import CalledProcessError
def whereis(app):
"""Return a list of locations a given application.
Relies on the `where` system command in Windows and the `whereis` command in Unix.
Parameters
----------
app : str
Can be any application on the system path e.g. java.
Returns
-------
result : list
A list of locations where applications is installed.
Useage
------
>>>whereis('javac')
'C:\Program Files\Java\jdk1.8.0_162\bin\javac.exe'
"""
result = None
if os.name == "nt":# Windows
try:
result = subprocess.check_output("where {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not forund.",err)
else:# Unix
try:
result = subprocess.check_output("whereis {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
print("")
result = []
return result
else:
result = result.decode().replace("r", "").split("n")
result = list(filter(lambda x: len(x)>0, result))
return result
Questions
- Is there a standard library function that already covers this? I couldn't find one but that doesn't mean anything.
- Are there any caveats or edge cases that I'm missing?
- Can any general improvements be made to the code or docstring?
python python-3.x windows unix
$endgroup$
add a comment |
$begingroup$
I'm trying to write a platform independent Python (>=3.6.5) package that has a handful of java .class files that need to compiled using javac and run using java. This is simple enough task but I need to know if user has these installed already and the location of the executable assuming that neither of them is on the system path. That way I can just call the executable by it's path using subprocess.run. Which bring me to the subject of this review a platform independent whereis command.
import os, subprocess
from subprocess import CalledProcessError
def whereis(app):
"""Return a list of locations a given application.
Relies on the `where` system command in Windows and the `whereis` command in Unix.
Parameters
----------
app : str
Can be any application on the system path e.g. java.
Returns
-------
result : list
A list of locations where applications is installed.
Useage
------
>>>whereis('javac')
'C:\Program Files\Java\jdk1.8.0_162\bin\javac.exe'
"""
result = None
if os.name == "nt":# Windows
try:
result = subprocess.check_output("where {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not forund.",err)
else:# Unix
try:
result = subprocess.check_output("whereis {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
print("")
result = []
return result
else:
result = result.decode().replace("r", "").split("n")
result = list(filter(lambda x: len(x)>0, result))
return result
Questions
- Is there a standard library function that already covers this? I couldn't find one but that doesn't mean anything.
- Are there any caveats or edge cases that I'm missing?
- Can any general improvements be made to the code or docstring?
python python-3.x windows unix
$endgroup$
I'm trying to write a platform independent Python (>=3.6.5) package that has a handful of java .class files that need to compiled using javac and run using java. This is simple enough task but I need to know if user has these installed already and the location of the executable assuming that neither of them is on the system path. That way I can just call the executable by it's path using subprocess.run. Which bring me to the subject of this review a platform independent whereis command.
import os, subprocess
from subprocess import CalledProcessError
def whereis(app):
"""Return a list of locations a given application.
Relies on the `where` system command in Windows and the `whereis` command in Unix.
Parameters
----------
app : str
Can be any application on the system path e.g. java.
Returns
-------
result : list
A list of locations where applications is installed.
Useage
------
>>>whereis('javac')
'C:\Program Files\Java\jdk1.8.0_162\bin\javac.exe'
"""
result = None
if os.name == "nt":# Windows
try:
result = subprocess.check_output("where {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not forund.",err)
else:# Unix
try:
result = subprocess.check_output("whereis {}".format(app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
print("")
result = []
return result
else:
result = result.decode().replace("r", "").split("n")
result = list(filter(lambda x: len(x)>0, result))
return result
Questions
- Is there a standard library function that already covers this? I couldn't find one but that doesn't mean anything.
- Are there any caveats or edge cases that I'm missing?
- Can any general improvements be made to the code or docstring?
python python-3.x windows unix
python python-3.x windows unix
edited Mar 30 '18 at 22:58
Jamal♦
30.3k11119227
30.3k11119227
asked Mar 30 '18 at 19:19
James DraperJames Draper
4012619
4012619
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
$begingroup$
A couple of small things:
If you're specifically looking for executable files, you might use
whichinstead ofwhereiscommand. From this answer, you can see the difference between the two usingwhatis:
$ whatis which
which (1) - shows the full path of (shell) commands
$ whatis whereis
whereis (1) - locate the binary, source, and manual page files for a command
Be consistent. You've used two different formatting styles:
"where {}".format(app)
and
"Application ,",app,", not forund.",err # you also have a spelling mistake here (forund -> found)
I'd recommend you use the former one
You should have at least two spaces before an inline comment
- You should put a space after the comma in almost every situation. (e.g:
print("Application,",app,", not found.",err)->print("Application,", app, ", not found.", err))
$endgroup$
add a comment |
$begingroup$
Small nit:
# Split this into individual lines - much easier to read
import os, subprocess
Reduce duplicate code and nesting (and also use which) - this is way too complicated for what it needs to be (I didn't test it though):
def whereis(app):
result = None
command = 'where'
if os.name != "nt":# Windows
command = 'which'
try:
result = subprocess.check_output("{} {}".format(command, app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
return []
result = result.decode().splitlines()
return [line for line in result if len(line)]
$endgroup$
add a comment |
$begingroup$
You can use a ternary conditional operator for determining the command per operating system, making that bit of logic a one liner. Unless necessary for your intended use, I don't see the point in returning an empty list, just return None if your script finds nothing. If you have a bit of code elsewhere that looks roughly like:
if not paths:
# do something
If paths is an empty list, it'll work exactly the same if we change it to None.
import os
import subprocess
def whereis(app):
command = 'which' if os.name != 'nt' else 'where'
try:
result = subprocess.check_output('{} {}'.format(command, app), stderr=subprocess.STDOUT)
return result.decode().split()
except subprocess.CalledProcessError:
return
if __name__ == '__main__':
paths = whereis('notepad')
Output:
['C:\Windows\System32\notepad.exe', 'C:\Windows\notepad.exe']
$endgroup$
add a comment |
$begingroup$
As far as I can see your code has zero escaping for spaces or shell characters, therefore I would assume it is highly insecure and could be easily used to take over / crash / ... the entire application when being passed malicious input.
You really need to be using shlex.quote or something similar, or use which as a non-bash built-in: subprocess.check_output(["which", your_argument])
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f190886%2fplatform-independent-whereis-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
A couple of small things:
If you're specifically looking for executable files, you might use
whichinstead ofwhereiscommand. From this answer, you can see the difference between the two usingwhatis:
$ whatis which
which (1) - shows the full path of (shell) commands
$ whatis whereis
whereis (1) - locate the binary, source, and manual page files for a command
Be consistent. You've used two different formatting styles:
"where {}".format(app)
and
"Application ,",app,", not forund.",err # you also have a spelling mistake here (forund -> found)
I'd recommend you use the former one
You should have at least two spaces before an inline comment
- You should put a space after the comma in almost every situation. (e.g:
print("Application,",app,", not found.",err)->print("Application,", app, ", not found.", err))
$endgroup$
add a comment |
$begingroup$
A couple of small things:
If you're specifically looking for executable files, you might use
whichinstead ofwhereiscommand. From this answer, you can see the difference between the two usingwhatis:
$ whatis which
which (1) - shows the full path of (shell) commands
$ whatis whereis
whereis (1) - locate the binary, source, and manual page files for a command
Be consistent. You've used two different formatting styles:
"where {}".format(app)
and
"Application ,",app,", not forund.",err # you also have a spelling mistake here (forund -> found)
I'd recommend you use the former one
You should have at least two spaces before an inline comment
- You should put a space after the comma in almost every situation. (e.g:
print("Application,",app,", not found.",err)->print("Application,", app, ", not found.", err))
$endgroup$
add a comment |
$begingroup$
A couple of small things:
If you're specifically looking for executable files, you might use
whichinstead ofwhereiscommand. From this answer, you can see the difference between the two usingwhatis:
$ whatis which
which (1) - shows the full path of (shell) commands
$ whatis whereis
whereis (1) - locate the binary, source, and manual page files for a command
Be consistent. You've used two different formatting styles:
"where {}".format(app)
and
"Application ,",app,", not forund.",err # you also have a spelling mistake here (forund -> found)
I'd recommend you use the former one
You should have at least two spaces before an inline comment
- You should put a space after the comma in almost every situation. (e.g:
print("Application,",app,", not found.",err)->print("Application,", app, ", not found.", err))
$endgroup$
A couple of small things:
If you're specifically looking for executable files, you might use
whichinstead ofwhereiscommand. From this answer, you can see the difference between the two usingwhatis:
$ whatis which
which (1) - shows the full path of (shell) commands
$ whatis whereis
whereis (1) - locate the binary, source, and manual page files for a command
Be consistent. You've used two different formatting styles:
"where {}".format(app)
and
"Application ,",app,", not forund.",err # you also have a spelling mistake here (forund -> found)
I'd recommend you use the former one
You should have at least two spaces before an inline comment
- You should put a space after the comma in almost every situation. (e.g:
print("Application,",app,", not found.",err)->print("Application,", app, ", not found.", err))
edited Mar 31 '18 at 9:31
answered Mar 30 '18 at 21:14
яүυкяүυк
7,16122054
7,16122054
add a comment |
add a comment |
$begingroup$
Small nit:
# Split this into individual lines - much easier to read
import os, subprocess
Reduce duplicate code and nesting (and also use which) - this is way too complicated for what it needs to be (I didn't test it though):
def whereis(app):
result = None
command = 'where'
if os.name != "nt":# Windows
command = 'which'
try:
result = subprocess.check_output("{} {}".format(command, app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
return []
result = result.decode().splitlines()
return [line for line in result if len(line)]
$endgroup$
add a comment |
$begingroup$
Small nit:
# Split this into individual lines - much easier to read
import os, subprocess
Reduce duplicate code and nesting (and also use which) - this is way too complicated for what it needs to be (I didn't test it though):
def whereis(app):
result = None
command = 'where'
if os.name != "nt":# Windows
command = 'which'
try:
result = subprocess.check_output("{} {}".format(command, app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
return []
result = result.decode().splitlines()
return [line for line in result if len(line)]
$endgroup$
add a comment |
$begingroup$
Small nit:
# Split this into individual lines - much easier to read
import os, subprocess
Reduce duplicate code and nesting (and also use which) - this is way too complicated for what it needs to be (I didn't test it though):
def whereis(app):
result = None
command = 'where'
if os.name != "nt":# Windows
command = 'which'
try:
result = subprocess.check_output("{} {}".format(command, app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
return []
result = result.decode().splitlines()
return [line for line in result if len(line)]
$endgroup$
Small nit:
# Split this into individual lines - much easier to read
import os, subprocess
Reduce duplicate code and nesting (and also use which) - this is way too complicated for what it needs to be (I didn't test it though):
def whereis(app):
result = None
command = 'where'
if os.name != "nt":# Windows
command = 'which'
try:
result = subprocess.check_output("{} {}".format(command, app))
except CalledProcessError as err:
print("Application ,",app,", not found.",err)
if result is None:
return []
result = result.decode().splitlines()
return [line for line in result if len(line)]
edited May 7 '18 at 16:04
Daniel
4,1632936
4,1632936
answered Mar 30 '18 at 22:06
Srdjan GruborSrdjan Grubor
26615
26615
add a comment |
add a comment |
$begingroup$
You can use a ternary conditional operator for determining the command per operating system, making that bit of logic a one liner. Unless necessary for your intended use, I don't see the point in returning an empty list, just return None if your script finds nothing. If you have a bit of code elsewhere that looks roughly like:
if not paths:
# do something
If paths is an empty list, it'll work exactly the same if we change it to None.
import os
import subprocess
def whereis(app):
command = 'which' if os.name != 'nt' else 'where'
try:
result = subprocess.check_output('{} {}'.format(command, app), stderr=subprocess.STDOUT)
return result.decode().split()
except subprocess.CalledProcessError:
return
if __name__ == '__main__':
paths = whereis('notepad')
Output:
['C:\Windows\System32\notepad.exe', 'C:\Windows\notepad.exe']
$endgroup$
add a comment |
$begingroup$
You can use a ternary conditional operator for determining the command per operating system, making that bit of logic a one liner. Unless necessary for your intended use, I don't see the point in returning an empty list, just return None if your script finds nothing. If you have a bit of code elsewhere that looks roughly like:
if not paths:
# do something
If paths is an empty list, it'll work exactly the same if we change it to None.
import os
import subprocess
def whereis(app):
command = 'which' if os.name != 'nt' else 'where'
try:
result = subprocess.check_output('{} {}'.format(command, app), stderr=subprocess.STDOUT)
return result.decode().split()
except subprocess.CalledProcessError:
return
if __name__ == '__main__':
paths = whereis('notepad')
Output:
['C:\Windows\System32\notepad.exe', 'C:\Windows\notepad.exe']
$endgroup$
add a comment |
$begingroup$
You can use a ternary conditional operator for determining the command per operating system, making that bit of logic a one liner. Unless necessary for your intended use, I don't see the point in returning an empty list, just return None if your script finds nothing. If you have a bit of code elsewhere that looks roughly like:
if not paths:
# do something
If paths is an empty list, it'll work exactly the same if we change it to None.
import os
import subprocess
def whereis(app):
command = 'which' if os.name != 'nt' else 'where'
try:
result = subprocess.check_output('{} {}'.format(command, app), stderr=subprocess.STDOUT)
return result.decode().split()
except subprocess.CalledProcessError:
return
if __name__ == '__main__':
paths = whereis('notepad')
Output:
['C:\Windows\System32\notepad.exe', 'C:\Windows\notepad.exe']
$endgroup$
You can use a ternary conditional operator for determining the command per operating system, making that bit of logic a one liner. Unless necessary for your intended use, I don't see the point in returning an empty list, just return None if your script finds nothing. If you have a bit of code elsewhere that looks roughly like:
if not paths:
# do something
If paths is an empty list, it'll work exactly the same if we change it to None.
import os
import subprocess
def whereis(app):
command = 'which' if os.name != 'nt' else 'where'
try:
result = subprocess.check_output('{} {}'.format(command, app), stderr=subprocess.STDOUT)
return result.decode().split()
except subprocess.CalledProcessError:
return
if __name__ == '__main__':
paths = whereis('notepad')
Output:
['C:\Windows\System32\notepad.exe', 'C:\Windows\notepad.exe']
answered Mar 31 '18 at 23:10
Lukasz SalitraLukasz Salitra
793216
793216
add a comment |
add a comment |
$begingroup$
As far as I can see your code has zero escaping for spaces or shell characters, therefore I would assume it is highly insecure and could be easily used to take over / crash / ... the entire application when being passed malicious input.
You really need to be using shlex.quote or something similar, or use which as a non-bash built-in: subprocess.check_output(["which", your_argument])
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
$begingroup$
As far as I can see your code has zero escaping for spaces or shell characters, therefore I would assume it is highly insecure and could be easily used to take over / crash / ... the entire application when being passed malicious input.
You really need to be using shlex.quote or something similar, or use which as a non-bash built-in: subprocess.check_output(["which", your_argument])
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
$begingroup$
As far as I can see your code has zero escaping for spaces or shell characters, therefore I would assume it is highly insecure and could be easily used to take over / crash / ... the entire application when being passed malicious input.
You really need to be using shlex.quote or something similar, or use which as a non-bash built-in: subprocess.check_output(["which", your_argument])
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
As far as I can see your code has zero escaping for spaces or shell characters, therefore I would assume it is highly insecure and could be easily used to take over / crash / ... the entire application when being passed malicious input.
You really need to be using shlex.quote or something similar, or use which as a non-bash built-in: subprocess.check_output(["which", your_argument])
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
answered 11 mins ago
J. T.J. T.
1
1
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
J. T. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f190886%2fplatform-independent-whereis-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown