Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
king_kilr
May 25, 2007

CrazyPanda posted:

Python webbrowser module question. When i open a new page, it opens it through internet explorer. How do i get the module to open through firefox?

webbrowser.get("firefox").open("http://goatse.cx")

Adbot
ADBOT LOVES YOU

TK422
Dec 22, 2007

I hate being right
Any way to compress these lines of code?

(I type them so frequently I may as well optimize)

code:
for line in lines:
    l = line.strip()
    ... # do stuff with l
I guess there's a good probability something like "for line.strip() in lines" exists in python. You get the idea

MaberMK
Feb 1, 2008

BFFs

TK422 posted:

Any way to compress these lines of code?

(I type them so frequently I may as well optimize)

code:
for line in lines:
    l = line.strip()
    ... # do stuff with l
I guess there's a good probability something like "for line.strip() in lines" exists in python. You get the idea

Compressing readable code into one-liners isn't optimization, it's just making code less readable. Stick with what you've got.

Also, l is an awful name for a variable; it looks too much like 1. Obviously you can't use 1 as a variable name anyway, but it's better to avoid for the sake of being easy to read. Personally, I'd just reuse line.

e: I totally misunderstood the question. line in lines is an assignment, so line in lines.strip() wouldn't work because you can't assign something to a function call. If lines is a list, you could map strip() to each element in the list, but then you'd effectively be looping over it twice so why even bother. If it's an iterator, you're stuck doing what you've got.

MaberMK fucked around with this message at 20:00 on Jan 3, 2011

leterip
Aug 25, 2004
You could also write a simple generator.

code:
def stripped(iterable):
  for line in iterable:
    yield line.strip()

for line in stripped(lines):
  # do stuff

Stabby McDamage
Dec 11, 2005

Doctor Rope

leterip posted:

You could also write a simple generator.

code:
def stripped(iterable):
  for line in iterable:
    yield line.strip()

for line in stripped(lines):
  # do stuff

Or just use a generator expression.

code:
for line in (line.strip() for line in lines): ...

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
That looks really dumb though.

DirtyDiaperMask
Aug 11, 2003

by Ozmaugh

TK422 posted:

Any way to compress these lines of code?

(I type them so frequently I may as well optimize)


code:
for line in lines:
    domorestuff(dostuff(line.strip()))
Alterntively

code:
stripper = (line.strip() for line in lines)
for line in stripper:
   # do stuff

ErIog
Jul 11, 2001

:nsacloud:

TK422 posted:

Any way to compress these lines of code?

(I type them so frequently I may as well optimize)

code:
for line in lines:
    l = line.strip()
    ... # do stuff with l
I guess there's a good probability something like "for line.strip() in lines" exists in python. You get the idea

Depending on where these strings are coming from you might want to think about scrubbing/validating via whatever function is giving you that data. That way you can operate on that input all you like without having to litter extra "line = line.strip()" in your code. You just attach that logic in the one place all input flows through, and then it becomes an assumption in your code that you're always working with pre-stripped strings.

Even if all you're doing is reading poo poo in from a text file, I find it generally handy to write a small generator like this:

code:
#Wraps file.readline to ignore blank lines, yields stripped lines
def scrubbed_text_file(file_path):
     file = open(file_path, "r")
          line = file.readline()
          while line:
               line = line.strip()
               if line != "":
                    yield(line.strip())

               line = file.readline()
     file.close()

ErIog fucked around with this message at 01:49 on Jan 4, 2011

Lurchington
Jan 2, 2003

Forums Dragoon

ErIog posted:

You might think about scrubbing/validating your input before it gets to any other part of your program? That way you can operate on that input all you like without having to litter extra "line = line.strip()" lines in your code.

Even if all you're doing is reading poo poo in from a text file, I find it generally handy to write a small generator like this:

code:
#Wraps file.readline to ignore blank lines and yield stripped lines
def scrubbed_text_file(file_path):
     file = open(file_path, "r")
          line = file.readline()
          while line:
               line = line.strip()
               if line != "":
                    yield line.strip()

               line = file.readline()
     file.close()

If you're going to the trouble of a data scrubbing function (which I do recommend), you can also use the "with" keyword to make sure you're covered on exceptions.

code:
#Wraps file.readline to ignore blank lines and yield stripped lines
def scrubbed_text_file(file_path):
     with open(file_path, "r") as _file:
          line = _file.readline()
          while line:
               line = line.strip()
               if line != "":
                    yield line.strip()

               line = _file.readline()

Lurchington fucked around with this message at 02:00 on Jan 4, 2011

ErIog
Jul 11, 2001

:nsacloud:

Lurchington posted:

If you're going to the trouble of a data scrubbing function (which I do recommend), you can also use the "with" keyword to make sure you're covered on exceptions.

I cut and pasted that function from one of the Facebook Puzzles scripts I was writing. The Facebook Puzzles target Python 2.5.2, and the "with" keyword wasn't added until 2.6. If I were to rewrite that piece of the script I would probably just pass that function an already open known valid file object, and then change the yield line to also force conversion to Unicode to make it generally useful for other projects that aren't anything to do with Facebook Puzzles.

ErIog fucked around with this message at 02:00 on Jan 4, 2011

Lurchington
Jan 2, 2003

Forums Dragoon
s'cool, saying more as a reminder for everyone, but you actually can use the with statement in 2.5 if you import it from __future__: "What's new in 2.5?" link

I had to do some Jython work which was also on 2.5.2 so I can empathize with having to go back in time like that

Scaevolus
Apr 16, 2007

Refactoring one short line of code into a complicated generator expression or function is not worth it.

Captain Capacitor
Jan 21, 2008

The code you say?

Lurchington posted:

s'cool, saying more as a reminder for everyone, but you actually can use the with statement in 2.5 if you import it from __future__: "What's new in 2.5?" link

I had to do some Jython work which was also on 2.5.2 so I can empathize with having to go back in time like that

More importantly, you can import few other key features that should have been implemented ages ago.

code:
from __future__ import braces

for i in xrange(20) {
    if i % 2 {
        print i
    }
}
Don't do this.

king_kilr
May 25, 2007

Scaevolus posted:

Refactoring one short line of code into a complicated generator expression or function is not worth it.

This. Stop with the idiocy, you're taking one perfectly normal line of code and making a whole thing out of it.

tef
May 30, 2004

-> some l-system crap ->

Scaevolus posted:

Refactoring one short line of code into a complicated generator expression or function is not worth it.

like 'reversed', 'zip', :v: but if it is worth doing it is probably in itertools (except flatten :smith:)

Jarl
Nov 8, 2007

So what if I'm not for the ever offended?
Ubuntu has Python 2.6 installed. Should I uninstall this before installing the latest version of Py3K or are there no clashing problems?

I think my only gripe with Python from what I superficially can tell is the lack of static type checking (a lot of bugs can be avoided this way instead of discovering them much later - yes, I know of unit-testing) and interfaces. Other than that it looks awesome, and I'm looking forward to playing around with it :)

Lurchington
Jan 2, 2003

Forums Dragoon
If I'm typing the same thing over and over in a program, I like pulling it into a function so I can simplify adding a log line or slightly refactoring based on what the real data is, etc.

tef posted:

like 'reversed', 'zip', :v: but if it is worth doing it is probably in itertools (except flatten :smith:)

Itertools is so great. One time I looked over it for way too long before I realized I could just do this to get a full combination of two iterables
code:
deck = [(rank, suit) for rank in xrange(1, 14) for suit in ('hearts', 'clubs', 'spades', 'diamonds')]
:smith:

Stabby McDamage
Dec 11, 2005

Doctor Rope

Jarl posted:

Ubuntu has Python 2.6 installed. Should I uninstall this before installing the latest version of Py3K or are there no clashing problems?

I think my only gripe with Python from what I superficially can tell is the lack of static type checking (a lot of bugs can be avoided this way instead of discovering them much later - yes, I know of unit-testing) and interfaces. Other than that it looks awesome, and I'm looking forward to playing around with it :)

You basically can't separate a modern Linux distribution from it's native python, since a bunch of built-in utilities rely on Python.

You can install a Python 3 package, which works, but all the nice distro-maintained python modules don't have python 3 variants, so you can't apt-get everything you need. You can compile your own Python of whatever version you want, but again, no distro-maintained modules.

It's a problem I've never really solved, mainly through lack of effort. I was going to run my own Python 2.7 out of /opt, but I needed numpy, spent 5 seconds looking at the numpy manual build instructions (e.g. make sure your FORTRAN compiler works) and lost interest. It's a pain, since I'm stuck on Python 2.5 on this box (Debian 5).

For me, getting a new Python natively included in the distro is half the reason for upgrading.

DirtyDiaperMask
Aug 11, 2003

by Ozmaugh

Lurchington posted:

Itertools is so great. One time I looked over it for way too long before I realized I could just do this to get a full combination of two iterables

Or you could use just itertools.product()

Captain Capacitor
Jan 21, 2008

The code you say?

Stabby McDamage posted:

It's a problem I've never really solved, mainly through lack of effort. I was going to run my own Python 2.7 out of /opt, but I needed numpy, spent 5 seconds looking at the numpy manual build instructions (e.g. make sure your FORTRAN compiler works) and lost interest. It's a pain, since I'm stuck on Python 2.5 on this box (Debian 5).

For me, getting a new Python natively included in the distro is half the reason for upgrading.

Virtualenv probably would have solved this problem for you.

Stabby McDamage
Dec 11, 2005

Doctor Rope

Captain Capacitor posted:

Virtualenv probably would have solved this problem for you.

I still don't see how that saves me from having to locate, download, and build packages from source, including numpy, which has a ton of obscure math library dependencies. I'm spoiled on apt-get...pulling anything manually is a pain.

I'd never support anything in production that didn't rely on the stock Python of its given Linux distro.

Jarl
Nov 8, 2007

So what if I'm not for the ever offended?

Stabby McDamage posted:

I still don't see how that saves me from having to locate, download, and build packages from source, including numpy, which has a ton of obscure math library dependencies. I'm spoiled on apt-get...pulling anything manually is a pain.

I'd never support anything in production that didn't rely on the stock Python of its given Linux distro.

I agree completely. When it comes do getting and installing anything manually on Linux I often sigh. With windows it's never a problem, but boy is it a bitch with Linux.

MaberMK
Feb 1, 2008

BFFs
It's not nearly as hard as you guys are making it out to be.

Install Python from source to an island (I use /usr/local/python<version>), put the alternate Python bin path at the front of your PATH, then install setuptools with the alternate Python. Install things with setuptools, drink beer, etc.

e: ignore that, it's not even that hard. Install an alternate Python to /usr and point the /usr/bin/python symlink back to the system's python when you're done. Execute /usr/bin/python<whatever> directly as needed.

MaberMK fucked around with this message at 22:50 on Jan 4, 2011

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Jarl posted:

With windows it's never a problem, but boy is it a bitch with Linux.

Try installing mysqldb on win7 for Python 2.7.

I ended up having to figure out how to compile it myself, and this is a common problem with it. :(

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

MaberMK posted:

It's not nearly as hard as you guys are making it out to be.

Install Python from source to an island (I use /usr/local/python<version>), put the alternate Python bin path at the front of your PATH, then install setuptools with the alternate Python. Install things with setuptools, drink beer, etc.

e: ignore that, it's not even that hard. Install an alternate Python to /usr and point the /usr/bin/python symlink back to the system's python when you're done. Execute /usr/bin/python<whatever> directly as needed.
Using an alternate prefix won't help when it comes to installing numpy

Stabby McDamage
Dec 11, 2005

Doctor Rope

Janin posted:

Using an alternate prefix won't help when it comes to installing numpy

I don't believe setuptools can locate the various math libraries and fortran toolchain I need and install them in the distro-provided way, correct?

I tried this...I have /opt/python27 and /opt/python31 with symlinks in /usr/bin, but no numpy = no deal, and the effort to get it was more than the effort of just using my native 2.5, where everything just works. I'm not saying it's not possible, just not worth it, especially when I hop around so many different Linux systems.

Captain Capacitor
Jan 21, 2008

The code you say?

Stabby McDamage posted:

I don't believe setuptools can locate the various math libraries and fortran toolchain I need and install them in the distro-provided way, correct?

I tried this...I have /opt/python27 and /opt/python31 with symlinks in /usr/bin, but no numpy = no deal, and the effort to get it was more than the effort of just using my native 2.5, where everything just works. I'm not saying it's not possible, just not worth it, especially when I hop around so many different Linux systems.

I'm sorry for continuing this topic but, how would Virtualenv not help in this instance? I have both Python 2.6, 2.7 and 3 on OSX, and have installed numpy two or three times now in various Virtualenvs with no problem.

MaberMK
Feb 1, 2008

BFFs

Janin posted:

Using an alternate prefix won't help when it comes to installing numpy

That's what virtualenv is for

Stabby McDamage
Dec 11, 2005

Doctor Rope

MaberMK posted:

That's what virtualenv is for

Can you post a link to a recipe that shows virtualenv getting a non-native python installed with numpy without a ton of problems on Ubuntu/Debian (or generic Linux)? I don't doubt that it's possible, but every google hit I find are people talking about problems they had doing so.

I'm not trying to be contrarian...I just don't see a working HOWTO out there, and I don't care to spend a bunch of time experimenting when I could be getting work done on my native 2.5.

EDIT: Just to clarify, the only files I let into /usr are from the package manager -- everything else goes into /opt or somewhere custom. I'm pretty sure virtualenv satisfies this rule, but I wanted to be clear.

Stabby McDamage
Dec 11, 2005

Doctor Rope
Leaving aside this virtualenv discussion for the moment, I have an actual problem:

I have multiple python processes being started concurrently by an external agent (a build system, to be exact). I need to do some bookkeeping in a coordinated way between them. The ideal form would be a shared python object, but I'll take a structured database or something if I have to.

What's the easiest way to get such a shared object in a multi-process-safe way? To be clear, I do NOT have control of the thing starting my processes, so I can't instantiate the object and fork myself...I need to pick up the shared object already in progress.

MaberMK
Feb 1, 2008

BFFs

Stabby McDamage posted:

Can you post a link to a recipe that shows virtualenv getting a non-native python installed with numpy without a ton of problems on Ubuntu/Debian (or generic Linux)? I don't doubt that it's possible, but every google hit I find are people talking about problems they had doing so.

I'm not trying to be contrarian...I just don't see a working HOWTO out there, and I don't care to spend a bunch of time experimenting when I could be getting work done on my native 2.5.

EDIT: Just to clarify, the only files I let into /usr are from the package manager -- everything else goes into /opt or somewhere custom. I'm pretty sure virtualenv satisfies this rule, but I wanted to be clear.

You don't need a howto, this is trivially easy.

mkvirtualenv --python=/path/to/whichever/python/you/need

MaberMK
Feb 1, 2008

BFFs

Stabby McDamage posted:

Leaving aside this virtualenv discussion for the moment, I have an actual problem:

I have multiple python processes being started concurrently by an external agent (a build system, to be exact). I need to do some bookkeeping in a coordinated way between them. The ideal form would be a shared python object, but I'll take a structured database or something if I have to.

What's the easiest way to get such a shared object in a multi-process-safe way? To be clear, I do NOT have control of the thing starting my processes, so I can't instantiate the object and fork myself...I need to pick up the shared object already in progress.

Since this is a build system, I would assume that your processes don't need a coordinated, universal state; i.e., each build process doesn't need to be fully aware of the work every other build process is doing. You just need to be able to pass a task to a worker, get its output, handle errors, etc. Are my assumptions correct?

Stabby McDamage
Dec 11, 2005

Doctor Rope

MaberMK posted:

Since this is a build system, I would assume that your processes don't need a coordinated, universal state; i.e., each build process doesn't need to be fully aware of the work every other build process is doing. You just need to be able to pass a task to a worker, get its output, handle errors, etc. Are my assumptions correct?

All things being equal, I would agree, but I'm doing something very complicated and unconventional...basically a kind of call graph generation for use in an experimental compiler.

A naive solution to my problem would be an atomic pickle. Something like:
code:
get_global_lock(lockfile)
fp = open(datafile, 'r+b')
my_data = pickle.load(fp)
# ... do stuff with my_data
fp.seek(0)
fp.truncate(0)
pickle.dump(my_data, fp)
fp.close()
release_global_lock(lockfile)
Obviously that's horrendous and insane...there has to be an existing technique for more fine-grained atomic data structure access, right?

Failing that, I could do something that just uses atomic appends, then collate it later. In this case, does anyone know the easiest way to do multiple atomic appends to file?

I know how I'd do all this stuff with C primitives, but I'm using Python because I don't want to bother implementing all that crap.

Stabby McDamage
Dec 11, 2005

Doctor Rope

MaberMK posted:

You don't need a howto, this is trivially easy.

mkvirtualenv --python=/path/to/whichever/python/you/need

code:
$ sudo apt-get install python-virtualenv
...
$ mkvirtualenv
bash: mkvirtualenv: command not found
That command doesn't exist for me. I do have 'virtulenv', let me try that...

code:
$ virtualenv
You must provide a DEST_DIR
Usage: virtualenv [OPTIONS] DEST_DIR

Options:
  --version           show program's version number and exit
  -h, --help          show this help message and exit
  -v, --verbose       Increase verbosity
  -q, --quiet         Decrease verbosity
  --clear             Clear out the non-root install and start from scratch
  --no-site-packages  Don't give access to the global site-packages dir to the
                      virtual environment
  --unzip-setuptools  Unzip Setuptools when installing it
Okay, it doesn't have a '--python' option, but let me run it with the default.
code:
$ mkdir v1
$ virtualenv v1
New python executable in v1/bin/python
Installing setuptools............done.
Cool, but that's the native Python 2.5, so it does me no good. Let me try running it with my custom-built Python 2.7.

code:
$ mkdir v2
$ $ /opt/python2.7/bin/python `which virtualenv` v2
Traceback (most recent call last):
  File "/usr/bin/virtualenv", line 5, in <module>
    from pkg_resources import load_entry_point
ImportError: No module named pkg_resources
No dice, and now I've lost interest. :( We haven't even gotten to numpy. Like I said, I'm sure there's a solution, but just using 2.5 is the path of least resistance.

MaberMK
Feb 1, 2008

BFFs

Stabby McDamage posted:

code:
$ sudo apt-get install python-virtualenv
...
$ mkvirtualenv
bash: mkvirtualenv: command not found
That command doesn't exist for me. I do have 'virtulenv', let me try that...

code:
$ virtualenv
You must provide a DEST_DIR
Usage: virtualenv [OPTIONS] DEST_DIR

Options:
  --version           show program's version number and exit
  -h, --help          show this help message and exit
  -v, --verbose       Increase verbosity
  -q, --quiet         Decrease verbosity
  --clear             Clear out the non-root install and start from scratch
  --no-site-packages  Don't give access to the global site-packages dir to the
                      virtual environment
  --unzip-setuptools  Unzip Setuptools when installing it
Okay, it doesn't have a '--python' option, but let me run it with the default.
code:
$ mkdir v1
$ virtualenv v1
New python executable in v1/bin/python
Installing setuptools............done.
Cool, but that's the native Python 2.5, so it does me no good. Let me try running it with my custom-built Python 2.7.

code:
$ mkdir v2
$ $ /opt/python2.7/bin/python `which virtualenv` v2
Traceback (most recent call last):
  File "/usr/bin/virtualenv", line 5, in <module>
    from pkg_resources import load_entry_point
ImportError: No module named pkg_resources
No dice, and now I've lost interest. :( We haven't even gotten to numpy. Like I said, I'm sure there's a solution, but just using 2.5 is the path of least resistance.

First, install an up-to-date virtualenv and install virtualenvwrapper. To everyone, if you aren't using virtualenvwrapper, you're only causing yourselves undue pain and suffering.

Either way, you don't need to run virtualenv with a specific python because it's just going to set up a new environment with the python binary you tell it to use (assuming you update and have the --python option).

Haystack
Jan 23, 2005





Stabby McDamage posted:

All things being equal, I would agree, but I'm doing something very complicated and unconventional...basically a kind of call graph generation for use in an experimental compiler.

A naive solution to my problem would be an atomic pickle. Something like:
code:
get_global_lock(lockfile)
fp = open(datafile, 'r+b')
my_data = pickle.load(fp)
# ... do stuff with my_data
fp.seek(0)
fp.truncate(0)
pickle.dump(my_data, fp)
fp.close()
release_global_lock(lockfile)
Obviously that's horrendous and insane...there has to be an existing technique for more fine-grained atomic data structure access, right?

Failing that, I could do something that just uses atomic appends, then collate it later. In this case, does anyone know the easiest way to do multiple atomic appends to file?

I know how I'd do all this stuff with C primitives, but I'm using Python because I don't want to bother implementing all that crap.

You could try an object database, eg. ZODB

DirtyDiaperMask
Aug 11, 2003

by Ozmaugh

Stabby McDamage posted:

No dice, and now I've lost interest. :( We haven't even gotten to numpy. Like I said, I'm sure there's a solution, but just using 2.5 is the path of least resistance.

Not that this helps you in the least, but apparently one of the new features of Python 3.2 is going to be the ability to use extension modules with multiple versions(post-3.2) of the Python interpreter.

Stabby McDamage
Dec 11, 2005

Doctor Rope

MaberMK posted:

First, install an up-to-date virtualenv and install virtualenvwrapper. To everyone, if you aren't using virtualenvwrapper, you're only causing yourselves undue pain and suffering.

Either way, you don't need to run virtualenv with a specific python because it's just going to set up a new environment with the python binary you tell it to use (assuming you update and have the --python option).

Wow, this worked. I was even able to install numpy in one command with pip. I have no idea how it side-stepped all the FORTRAN/ATLAS/library requirements I hit when trying to install by hand, but more power to it. It flashed up a bunch of "don't know how to compile Fortran code on platform 'posix'", but somehow succeeded (?). I guess all that Fortran code was optional?

EDIT: I use a bunch of different Linux boxes, so I put together a script for dependency-free creation of a Python 2.7 virtualenv.

code:
PYVER=2.7.1
PYPATH=~/python2.7
VPYPATH=~/vpython2.7

mkdir -p $PYPATH  &&
wget -c [url]http://www.python.org/ftp/python/[/url]$PYVER/Python-$PYVER.tgz  &&
echo Extracting...

tar xf Python-$PYVER.tgz  &&
cd Python-$PYVER/  &&
./configure --prefix=$PYPATH && make -j2 && make install  &&
cd ..
echo Python installed.

wget -c [url]http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.5.1.tar.gz[/url]  &&
tar xf virtualenv-1.5.1.tar.gz  &&
cd virtualenv-1.5.1/  &&
mkdir -p $VPYPATH  &&
$PYPATH/bin/python virtualenv.py $VPYPATH  &&
echo Virtualenv created.

$VPYPATH/bin/pip install numpy  &&
echo Numpy installed.

echo Done.  Your python is: $VPYPATH/bin/python
EDIT2: All my scripts start with #!/usr/bin/python and I can't be bothered to change them to /usr/bin/env, so I'll still be sailing with 2.5 for most stuff. :stare:

Stabby McDamage fucked around with this message at 23:42 on Jan 5, 2011

Dren
Jan 5, 2001

Pillbug

Stabby McDamage posted:

Leaving aside this virtualenv discussion for the moment, I have an actual problem:

I have multiple python processes being started concurrently by an external agent (a build system, to be exact). I need to do some bookkeeping in a coordinated way between them. The ideal form would be a shared python object, but I'll take a structured database or something if I have to.

What's the easiest way to get such a shared object in a multi-process-safe way? To be clear, I do NOT have control of the thing starting my processes, so I can't instantiate the object and fork myself...I need to pick up the shared object already in progress.

This sounds like a job for Pyro.

Adbot
ADBOT LOVES YOU

Stabby McDamage
Dec 11, 2005

Doctor Rope

Dren posted:

This sounds like a job for Pyro.

It's all on one machine, so I think the ZODB recommended earlier is probably a better fit. We'll see.

  • Locked thread