diff --git a/.travis.yml b/.travis.yml
index 16f9cb1..c61f980 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,18 +5,15 @@ python:
   - 3.4
   - 3.5
   - 3.6
+  - 3.7
+  - 3.8
+  - 3.9-dev
   - pypy
   - pypy3.5
 matrix:
-  include:
-  # See https://github.com/travis-ci/travis-ci/issues/9069
-  # for more information.
-  - python: 3.7
-    sudo: required
-    dist: xenial
-  - python: 3.8-dev
-    sudo: required
-    dist: xenial
+  fast_finish: true
+  allow_failures:
+    - python: 3.9-dev
 cache: pip
 install:
   - pip install tox-travis
diff --git a/MANIFEST.in b/MANIFEST.in
index b12a6fe..81e72d5 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,4 @@
 include README.rst AUTHORS LICENSE CHANGES
 include setuputils.py
+include astor/VERSION
 recursive-include tests *.py
diff --git a/astor/VERSION b/astor/VERSION
new file mode 100644
index 0000000..a3df0a6
--- /dev/null
+++ b/astor/VERSION
@@ -0,0 +1,1 @@
+0.8.0
diff --git a/astor/__init__.py b/astor/__init__.py
index 3b02983..bdedaef 100644
--- a/astor/__init__.py
+++ b/astor/__init__.py
@@ -9,6 +9,7 @@ Copyright 2013 (c) Berker Peksag
 
 """
 
+import os
 import warnings
 
 from .code_gen import SourceGenerator, to_source  # NOQA
@@ -19,7 +20,9 @@ from .op_util import get_op_symbol, get_op_precedence  # NOQA
 from .op_util import symbol_data  # NOQA
 from .tree_walk import TreeWalk  # NOQA
 
-__version__ = '0.8.0'
+ROOT = os.path.dirname(__file__)
+with open(os.path.join(ROOT, 'VERSION')) as version_file:
+    __version__ = version_file.read().strip()
 
 parse_file = code_to_ast.parse_file
 
diff --git a/astor/code_gen.py b/astor/code_gen.py
index 0d8bd6b..4a634cf 100644
--- a/astor/code_gen.py
+++ b/astor/code_gen.py
@@ -604,6 +604,7 @@ class SourceGenerator(ExplicitNodeVisitor):
                             if getattr(value, 'expr_text', None):
                                 self.write(value.expr_text)
                             else:
+                                set_precedence(value, value.value)
                                 self.visit(value.value)
                             if value.conversion != -1:
                                 self.write('!%s' % chr(value.conversion))
diff --git a/astor/op_util.py b/astor/op_util.py
index e546528..e54e88b 100644
--- a/astor/op_util.py
+++ b/astor/op_util.py
@@ -34,6 +34,7 @@ op_data = """
         ExtSlice                1
     comprehension_target        1
            Tuple                0
+  FormattedValue                0
 
            Comma                1
        NamedExpr                1
diff --git a/docs/changelog.rst b/docs/changelog.rst
index f7d0e6a..d7046e7 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -2,6 +2,19 @@
 Release Notes
 =============
 
+0.8.1 - in development
+----------------------
+
+Bug fixes
+~~~~~~~~~
+
+* Fixed precedence issue for f-string expressions that caused
+  redundant parenthesis around expression.
+  (Reported by Ilya Kamenshchikov in `Issue 153`_ and fixed by Batuhan Taskaya in `PR 155`_.)
+
+.. _`Issue 153`: https://github.com/berkerpeksag/astor/issues/153
+.. _`PR 155`: https://github.com/berkerpeksag/astor/pull/155
+
 0.8.0 - 2019-05-19
 ------------------
 
diff --git a/setup.cfg b/setup.cfg
index 1baf6fc..a43634f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,6 +2,7 @@
 name = astor
 description = Read/rewrite/write Python ASTs
 long_description = file:README.rst
+version = file: astor/VERSION
 author = Patrick Maupin
 author_email = pmaupin@gmail.com
 platforms = Independent
@@ -40,7 +41,7 @@ test_suite = nose.collector
 [options.packages.find]
 exclude = tests
 
-[wheel]
+[bdist_wheel]
 universal = 1
 
 [build-system]
diff --git a/setup.py b/setup.py
index 4a111b5..6068493 100644
--- a/setup.py
+++ b/setup.py
@@ -1,17 +1,3 @@
-import os
-import sys
-
 from setuptools import setup
-from setuptools.config import read_configuration
-
-from setuputils import find_version
-
-
-def here(*paths):
-    return os.path.join(os.path.dirname(__file__), *paths)
-
-config = read_configuration(here('setup.cfg'))
-config['metadata']['version'] = find_version(here('astor', '__init__.py'))
-config['options'].update(config['metadata'])
 
-setup(**config['options'])
+setup()

parenthesis around expressions in a JoinedString
Astor wraps expressions into parenthesis, also when this is completely redundant:

```
code = '''print(f"{var + 1:.2f}")'''

import ast
tree = ast.parse(code)
import astor
recovered = astor.to_source(tree)

print('original:   ',code)
print('astor:      ',recovered)
```

output:

```
original:    print(f"{var + 1:.2f}")
astor:       print(f'{(var + 1):.2f}')
```

Python: 3.6.8
astor: 0.8.0


diff --git a/tests/test_code_gen.py b/tests/test_code_gen.py
index 3cb7e64..45df8c0 100644
--- a/tests/test_code_gen.py
+++ b/tests/test_code_gen.py
@@ -171,9 +171,11 @@ class CodegenTestCase(unittest.TestCase, Comparisons):
         def test(a, b, /, c, *, d, **kwargs):
             pass
 
+
         def test(a=3, b=4, /, c=7):
             pass
 
+
         def test(a, b=4, /, c=8, d=9):
             pass
         """
@@ -456,6 +458,7 @@ class CodegenTestCase(unittest.TestCase, Comparisons):
         x = f'{int(x)}'
         x = f'a{b:c}d'
         x = f'a{b!s:c{d}e}f'
+        x = f'{x + y}'
         x = f'""'
         x = f'"\\''
         """

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/berkerpeksag/astor.git@3a7607e31f0c17e747ded5cfe0b582d99f7caecf#egg=astor
exceptiongroup==1.2.2
iniconfig==2.1.0
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
tomli==2.2.1

name: astor
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - tomli==2.2.1
prefix: /opt/conda/envs/astor

tests/test_code_gen.py::CodegenTestCase::test_fstrings
tests/test_code_gen.py::CodegenTestCase::test_huge_int
tests/test_code_gen.py::CodegenTestCase::test_annassign tests/test_code_gen.py::CodegenTestCase::test_arguments tests/test_code_gen.py::CodegenTestCase::test_assignment_expr tests/test_code_gen.py::CodegenTestCase::test_async_comprehension tests/test_code_gen.py::CodegenTestCase::test_async_def_with_for tests/test_code_gen.py::CodegenTestCase::test_attribute tests/test_code_gen.py::CodegenTestCase::test_class_definition_with_starbases_and_kwargs tests/test_code_gen.py::CodegenTestCase::test_compile_types tests/test_code_gen.py::CodegenTestCase::test_complex tests/test_code_gen.py::CodegenTestCase::test_comprehension tests/test_code_gen.py::CodegenTestCase::test_constant_nodes tests/test_code_gen.py::CodegenTestCase::test_del_statement tests/test_code_gen.py::CodegenTestCase::test_deprecated_constant_nodes tests/test_code_gen.py::CodegenTestCase::test_deprecated_name_constants tests/test_code_gen.py::CodegenTestCase::test_dictionary_literals tests/test_code_gen.py::CodegenTestCase::test_docstring_class tests/test_code_gen.py::CodegenTestCase::test_docstring_function tests/test_code_gen.py::CodegenTestCase::test_docstring_method tests/test_code_gen.py::CodegenTestCase::test_docstring_module tests/test_code_gen.py::CodegenTestCase::test_double_await tests/test_code_gen.py::CodegenTestCase::test_elif tests/test_code_gen.py::CodegenTestCase::test_empty_iterable_literals tests/test_code_gen.py::CodegenTestCase::test_fstring_debugging tests/test_code_gen.py::CodegenTestCase::test_fstring_escaped_braces tests/test_code_gen.py::CodegenTestCase::test_fstring_trailing_newline tests/test_code_gen.py::CodegenTestCase::test_imports tests/test_code_gen.py::CodegenTestCase::test_inf tests/test_code_gen.py::CodegenTestCase::test_matrix_multiplication tests/test_code_gen.py::CodegenTestCase::test_multiple_call_unpackings tests/test_code_gen.py::CodegenTestCase::test_nan tests/test_code_gen.py::CodegenTestCase::test_non_string_leakage tests/test_code_gen.py::CodegenTestCase::test_output_formatting tests/test_code_gen.py::CodegenTestCase::test_pass_arguments_node tests/test_code_gen.py::CodegenTestCase::test_positional_only_arguments tests/test_code_gen.py::CodegenTestCase::test_pow tests/test_code_gen.py::CodegenTestCase::test_right_hand_side_dictionary_unpacking tests/test_code_gen.py::CodegenTestCase::test_slicing tests/test_code_gen.py::CodegenTestCase::test_try_expect tests/test_code_gen.py::CodegenTestCase::test_tuple_corner_cases tests/test_code_gen.py::CodegenTestCase::test_unary tests/test_code_gen.py::CodegenTestCase::test_unicode_literals tests/test_code_gen.py::CodegenTestCase::test_with tests/test_code_gen.py::CodegenTestCase::test_yield
MANIFEST.in setup.py docs/changelog.rst .travis.yml setup.cfg astor/VERSION astor/__init__.py astor/code_gen.py astor/op_util.py
MANIFEST.in setup.py docs/changelog.rst .travis.yml setup.cfg astor/VERSION astor/__init__.py astor/code_gen.py astor/op_util.py