Raise an error when pickling or copying FlagValues()

Deep copying flags (with copy.deepcopy) is still allowed. Pickling and shallow
are now prohibited, because the notion of a shallow copy isn't entirely well
defined -- should an unpickled flag or shallow copy link back to the original
flag value?

FlagValues() already cannot be successfully serialized/deserialized with
pickle. But the error message is unrelated and raised when attempting to
*load* pickled FlagValues instances, not when saving them:

  >>> from absl import flags
  >>> import pickle
  >>> dumped = pickle.dumps(flags.FLAGS)  # no error
  >>> pickle.loads(dumped)
  Traceback (most recent call last)
  <ipython-input-5-5a8322d34219> in <module>()
  ----> 1 pickle.loads(dumped)

  /usr/lib/python2.7/pickle.pyc in loads(str)
     1386 def loads(str):
     1387     file = StringIO(str)
  -> 1388     return Unpickler(file).load()
     1389
     1390 # Doctest

  /usr/lib/python2.7/pickle.pyc in load(self)
      862             while 1:
      863                 key = read(1)
  --> 864                 dispatch[key](self)
      865         except _Stop, stopinst:
      866             return stopinst.value

  /usr/lib/python2.7/pickle.pyc in load_build(self)
     1219         state = stack.pop()
     1220         inst = stack[-1]
  -> 1221         setstate = getattr(inst, "__setstate__", None)
     1222         if setstate:
     1223             setstate(state)

  /usr/local/lib/python2.7/dist-packages/absl/flags/_flagvalues.pyc in __getattr__(self, name)
      466   def __getattr__(self, name):
      467     """Retrieves the 'value' attribute of the flag --name."""
  --> 468     fl = self._flags()
      469     if name not in fl:
      470       raise AttributeError(name)

  /usr/local/lib/python2.7/dist-packages/absl/flags/_flagvalues.pyc in _flags(self)
      139
      140   def _flags(self):
  --> 141     return self.__dict__['__flags']
      142
      143   def flags_by_module_dict(self):

  KeyError: '__flags'

This change causes an error to be raised earlier (as part of serialization
rather than deserialization) and with a better error message, e.g.,

  >>> pickle.dumps(flags.FLAGS)
  TypeError: can't pickle FlagValues

PiperOrigin-RevId: 213728792
4 files changed
tree: 14a82fd7500c0d78a2055d8cbf665aa20a27dfbc
  1. absl/
  2. smoke_tests/
  3. third_party/
  4. AUTHORS
  5. CONTRIBUTING.md
  6. LICENSE
  7. README.md
  8. setup.py
  9. WORKSPACE
README.md

Abseil Python Common Libraries

This repository is a collection of Python library code for building Python applications. The code is collected from Google's own Python code base, and has been extensively tested and used in production.

Features

  • Simple application startup
  • Distributed commandline flags system
  • Custom logging module with additional features
  • Testing utilities

Getting Started

Installation

To install the package, simply run:

pip install absl-py

Or install from source:

python setup.py install

Running Tests

To run Abseil tests, you can clone the git repo and run bazel:

git clone git@github.com:abseil/abseil-py.git
cd abseil-py
bazel test absl/...

Example Code

Please refer to smoke_tests/sample_app.py as an example to get started.

Documentation

Full documentation is forthcoming on https://abseil.io. For now, please refer to the in-code Python docstrings.

Future Releases

The current repository includes an initial set of libraries for early adoption. More components and interoperability with Abseil C++ Common Libraries will come in future releases.

License

The Abseil Python library is licensed under the terms of the Apache license. See LICENSE for more information.