Releases: Privex/python-helpers
3.2.0 - Added MemcachedCache + privex.helpers.cache.extra, plus various other additions
-
privex.helpers.settings
-
Added
DEFAULT_CACHE_ADAPTERwhich can be adjusted via the env varPRIVEX_CACHE_ADAPTER. This setting allows overriding the cache adapter which is used automatically by default viacached/async_cached, along with the global adapter when you callget_adapter -
Added
DEFAULT_ASYNC_CACHE_ADAPTERwhich can be adjusted via the env varPRIVEX_ASYNC_CACHE_ADAPTER.It defaults to the same value as
DEFAULT_CACHE_ADAPTER, since thanks to the newimport_adapterfunction andADAPTER_MAPdictionary inprivex.helpers.cache, it's now possible to reference cache adapters by simple names such asmemcached,redis,sqlite3,memoryetc. - and these aliases point to either the synchronous or asyncio version of their related adapter depending on which context they're being passed into.
-
-
privex.helpers.cache
-
Added
MemcachedCachemodule, which contains the synchronous cache adapterMemcachedCache. This is simply a synchronous version ofAsyncMemcachedCachethat usespylibmcinstead ofaiomcache. -
Added
ADAPTER_MAPdictionary, which maps aliases such asmemcached,redis,sqlite3,memoryetc. to their respective synchronous and asyncio adapter module paths, which can be loaded using the newly addedimport_adapterfunction, or simply usingadapter_set/async_adapter_set. -
Added
import_adapterfunction, which looks up an adapter alias name such asredis/memcached, maps it to the fully qualified module path viaADAPTER_MAP, and then loads the module + extracts the class from the module. -
Adjusted
adapter_set,async_adapter_set, along withCacheWrapper+AsyncCacheWrapperso that they now use the default string cache adapter defined insettings, and can transparently handle string adapter values by passing them off toimport_adapter. -
Added new
extrasmodule-
CacheManagerMixinis a class mixin which adds various methods and settings to assist with class-scoped caching, including an adjustable class-level cache prefix.cache_prefix, a method to remove all known cache keys managed by your class.clear_all_cache_keys, and a special decorator which automatically integrates with your class.z_cacheby intercepting the first argument of a method call. -
z_cache- A special method caching decorator which is designed to integrate with classes that extend.CacheManagerMixinThis is simply a wrapper for
.r_cache- it transparently caches the output of a wrapped method/function, but unlike.r_cache, it's designed to automatically integrate with classes which extend.CacheManagerMixin, allowing it to automatically retrieve cache settings such as the cache prefix, default cache time, along with directly calling various classmethods which enable logging of newly createdcache_key's for painless cleanup of cache keys when needed, without having to manually track them, or doing the nuclear option of erasing the entire cache system's database.
-
-
-
privex.helpers.common
- Added new small helper function
auto_list, which is a small but useful function that simplifies the conversion of objects into lists, sets, tuples etc. with the option to manually force a certain conversion method, eitherlist wrappingorlist iteration
- Added new small helper function
-
privex.helpers.plugin
- Added various functions for managing memcached instances via the
pylibmclibraryconnect_memcached- create a new memcachedClientobjectget_memcached- get or create a MemcachedClientobject shared by your threadclose_memcached- close the MemcachedClientconnection and delete it from the threadstorereset_memcached- close the sharedClientthen re-create it again.configure_memcached- configure Memcached settings then automatically reset the sharedClientinstance.
- Added new
HAS_MEMCACHEDboolean value, to track whether synchronous memcached viapylibmcis available
- Added various functions for managing memcached instances via the
-
General stuff
- Added
pylibmcto extras/cache.txt - Added some missing packages to the
Pipfile- and synchronisedPipfile.lock - Added
.envto.gitignore - Created unit tests for the new
CacheManagerMixinclass andz_cachedecorator - Created unit tests for the new
MemcachedCachecache adapter - Fixed the
livecommand indocs/Makefilefor newersphinx-autobuild - Added
SqliteCacheandMemcachedCacheto the docs - Added
privex.helpers.cache.extrasandprivex.helpers.cache.post_depto the docs - Added some other missing things to the docs
- Created and updated a lot of stub files in
privex_stubs(assists IDEs like PyCharm with type hinting and function/method previews) - Possibly other various additions / fixes / improvements that I forgot to list.
- Added
3.1.0 - Added SqliteCache + AsyncSqliteCache, plus minor fixes in privex.helpers.plugin
privex.helpers.cache
-
Added
SqliteCachemodule, containing the synchronous cache adapterSqliteCachewhich uses an Sqlite3 database for persistent cache storage without the need for any extra system service (unlike the memcached / redis adapters) -
Added
asyncx.AsyncSqliteCachemodule, containing the AsyncIO cache adapterAsyncSqliteCache, which is simply an AsyncIO version ofSqliteCacheusing theaiosqlitelibrary.- NOTE: Due to the file-based nature of SQLite3, combined with the fact write operations generally result in the database being locked until the write is completed - use of the AsyncIO SQLite3 cache adapter only slightly improves performance, due to the blocking single-user nature of SQLite3.
-
Added
post_depsmodule, short for post-init dependencies. This module contains functions and classes which are known to have (or have a high risk of) recursive import conflicts - e.g. the new SQLite caching uses theprivex-dbpackage, and theprivex-dbpackage imports various things fromprivex.helperscausing a recursive import issue if we loadprivex.dbwithin a class that's auto-loaded in an__init__.pyfile.The nature of this module means that none of it's contents are auto-loaded / aliased using
__init__.pymodule constructor files. This shouldn't be a problem for most people though, as the functions/classes etc. within the module are primarily only useful for certain cache adapter classes, rather than intended for use by the users ofprivex-helpers(though there's nothing stopping you from importing things frompost_depsin your own project).sqlite_cache_set_dbfolderandsqlite_cache_set_dbnameare two module level functions that are intended for use by users. These functions allow you to quickly override theDEFAULT_DB_FOLDERand/orDEFAULT_DB_NAMEdynamically for both SqliteCacheManager and AsyncSqliteCacheManager.SqliteCacheResultis a namedtuple that represents a row returned when querying thepvcachetable within an SQLite cache database_SQManagerBaseis a mix-in class used by bothSqliteCacheManagerandAsyncSqliteCacheManager, containing code which is used by both classes.SqliteCacheManageris a child class ofSqliteWrapper, designed to provide easier interaction with an SQLite3 cache database, including automatic creation of the database file, and thepvcachetable within it. This class is intended for use byprivex.helpers.cache.SqliteCacheAsyncSqliteCacheManageris a child class ofSqliteAsyncWrapper, and is simply an AsyncIO version ofSqliteCacheManager. This class is intended for use byprivex.helpers.cache.asyncx.AsyncSqliteCache
privex.helpers.plugins
- Added
HAS_PRIVEX_DBattribute, for tracking whether theprivex-dblibrary is available for use. - Added
clean_threadstoreto__all__- seems I forgot to add it previously.
privex.helpers.settings
- Added
SQLITE_APP_DB_NAMEwhich can also be controlled via an env var of the same name - allowing you to adjust the base of the default DB filename for the SQLite3 cache adapters. - Added
SQLITE_APP_DB_FOLDER(can also be controlled via env) - similar to the DB_NAME attribute, controls the default base folder used by the SQLite3 cache adapters.
3.0.0 - Overhauled net module, new object cleaner for easier serialisation, improved class generation/mocking + more
Key Additions and Changes
-
privex.helpers.common- Added
strip_null- very simple helper function to strip both\00and white space
from a string - with 2 cycles for good measure.
- Added
-
privex.helpers.types- Added
AUTO/AUTOMATIC/AUTO_DETECTEDdummy type, for use as the default value
of function/method parameters, signalling to users that a parameter is auto-populated
from another data source (e.g. instance/class attribute) if not specified.
- Added
-
privex.helpers.collections- Added
copy_class_simple(alternative tocopy_class) - Added
copy_funcfor copying functions, methods, and classmethods - Improved
_q_copyto handle copying functions, methods and classmethods - Added
generate_class+generate_class_kw - Added
Mocker.make_mock_module - Added
Mocker.add_mock_modules - Added
Mocker.__dir__to track the available mock attributes and modules - Added
dataclasses_mock- aMockerinstance which emulatesdataclassesas a drop-in
partially functional dummy for Python 3.6 when thedataclassesbackport package isn't installed. - Various changes to
Mocker.make_mock_class- potentially breaking, see the BREAKING CHANGES section. - Added
DictObject.__dir__+OrderedDictObject.__dir__to enable proper tracking of dictionary keys as attributes
- Added
-
privex.helpers.net-
This module has now been converted into a folder-based module. Imports in
__init__.pyhave been carefully setup to ensure that existing import statements should still work as normal -
Added new
SocketWrapperandAsyncSocketWrapperclasses, which are powerful wrapper classes for working with Pythonsocket.socketobjects, including support for SSL/TLS, partial support for running socket servers, and making basic HTTP requests -
Many, many new functions and classes! There's too many to list, and due to the conversion into a module folder instead of a singular file, it's difficult to track which functions/classes are new, and which existed before.
If you really want to know what's new, just take a look around the
privex/helpers/netmodule.
-
-
privex.helpers.converters- Added
clean_obj- which is a function that recursively "cleans" any arbitrary object, as to make it safe to convert into JSON and other common serialisation formats. It supportsdict's,list's, attrs objects, native Pythondataclass's,Decimal, and many other types of objects. - Added
clean_dict(used byclean_obj, usually no need to call it directly) - Added
clean_list(used byclean_obj, usually no need to call it directly)
- Added
-
Added
privex.helpers.mockersmodule, which contains pre-madeMockerobjects that are designed to stand-in for certain libraries / classes as partially functional dummies, if the real module(s) are unavailable for whatever reason. -
And probably some other small additions / changes
BREAKING CHANGES
-
Both
_copy_class_dictand_copy_class_slottednow check each attribute name against a blacklist (default:COPY_CLASS_BLACKLIST), and the default blacklist contains__dict__,__slots__and__weakref__, as the first 2 can't be directly copied (but we copy their contents by iteration), and weakref simply can't be deep copied (and it probably isn't a good idea to copy it anyway). -
_copy_class_dict(used bycopy_class) no longer breaks the attribute copy loop ifdeep_copy=False -
Mocker.make_mock_classnow returns a clonedMockerclass or instance by default, instead of a barebones class / instance of a barebones class.This was done simply because a Mocker class/instance is designed to handle being instantiated with any combination of constructor arguments, and have arbitrary attributes be retrieved / methods called without raising errors.
If you absolutely require a plain, simple, empty class to be generated, you may pass the parameter
simple=Trueto generate a bare class instead of a clone of Mocker (similar to the old behaviour). Unlike the old version of this method, you can now specify attributes as a dictionary to make your barebones mock class act similar to the class it's mocking. -
Many things in
privex.helpers.netsuch ascheck_host/check_host_asynchave been improved in various ways, however
there may be some breaking changes with certainprivex.helpers.netfunctions/classes in certain usecases.-
Due to the high risk of bugs with certain networking functions that have been completely revamped, the older, simpler versions of various networking functions are available under
privex.helpers.net.basewith their original names.Because of the naming conflicts, to use the legacy functions/classes from
base, you must import them directly fromprivex.helpers.net.baselike so:# Option 1: import the base module itself, with an alias to prevent naming conflicts (and make it more # clear what you're referencing) from privex.helpers.net import base as netbase if netbase.check_host('google.com', 80): print('google.com is up') # Option 2: import the required legacy functions directly (optionally, you can alias them as needed) # You could also alias the newer overhauled functions while testing them in small portions # of your application. from privex.helpers.net.base import check_host from privex.helpers.net import check_host as new_check_host if check_host('www.privex.io', 443, http_test=True, use_ssl=True): print('[old check_host] https://www.privex.io is up') if new_check_host('files.privex.io', 443, http_test=True, use_ssl=True): print('[new check_host] https://files.privex.io is up')
-
2.14.0 - new helpers.thread module + improved convert_datetime + fixes
-
privex.helpers.thread(new module)-
Added
lock_acquire_timeoutcontext manager function, for acquiring locks onthreading.Lockobjects
using awith lock_acquire_timeout(lock)context manager, allowing the use of a context manager, while still
being able to set a timeout / control blocking, plus the option to raise an exception on timeout. -
Added
BetterEvent- a modified version ofthreading.Eventwith more flexibility, such as the ability to
wait for "clear" state AND "set" state - not just "set" state. -
Added
StopperThread- athreading.Threadsub-class which comes with thread instance events allowing you
to signal a thread to stop/start/pause/unpause without having to constantly re-create stop/pause signalling. -
Added
SafeLoopThread- based onStopperThread, which is a looping thread with stop/pause signalling support,
along with two queue's pre-included on the instance:in_queuefor sending objects to the thread,
andout_queuefor receiving objects from the thread. -
Added
event_multi_waitwhich allows for waiting on multiple thread Event's usingthreading.Event.wait, and
some extra features if you pass Privex Helper'sBetterEventevents instead of standard events.
-
-
privex.helpers.convertersconvert_datetimecan now handledatetime.dateobjects, and also attempts to fallback to converting
the passed object into a string and parsing the string result if it's not a supported type.- Added aliases
parse_datetimeandparse_dateforconvert_datetime - Added aliases
parse_unixtime,parse_epochandconvert_epoch_datetimeforconvert_unixtime_datetime
-
privex.helpers.exceptions- Added
LockConflictexception for failed attempts at acquiringthreading.Lockorasyncio.Lockobjects. - Added
LockWaitTimeout- a more specific sub-class ofLockConflictfor lock acquisition timeouts - Added
EventWaitTimeout- for timeouts related tothreading.Event
- Added
-
Possibly some other minor changes
Unit Testing
-
Adjusted timing for
tests.cache.test_async_memcachedto avoid race condition test bug where sometimes
it would take too long to get the cache item to update it, and result in the item expiring before it can
be updated. -
Added more unit tests to
test_converters- Test
convert_datetimehandling ofdatetime.dateobjects - Test
convert_datetimehandling of byte-strings - Test
convert_datetimehandling of just string dates without times
- Test
-
Added new
test_threadmodule which tests a good portion of the newprivex.helpers.threadmodule.
2.9.0 - Added tail, io_tail, and reverse_io functions. Fixed some unit tests
Added in main commit 48ce4b6
-
Added
common.reverse_iofunction, allows reading blocks of bytes from files from the end of the file efficiently. -
Added
common.io_tailfunction, a pure python generator function, which works similarly to UNIXtail, and
efficiently reads the file from the end, instead of having to load the entire file to access the last lines. -
Added
common.tailfunction, which is a simple wrapper aroundio_tail- to simplify usage when tailing a relatively small ( < 10k lines? )
amount of lines. Iterates overio_tail, loading each chunk into memory, and correctly orders the lines for immediate usage of the returned list. -
Added
io_tail,reverse_ioandtailto the docs. -
Added thorough unit tests for
io_tailandtail -
Minor cleanup of whitespace in
common.py
Additional commit to fix unit tests 47345a2
-
tests.test_net.TestNet._check_asnnow allows comparing against multiple AS names,
reducing risk of ASN test breakage due to AS names changing. -
Added additional AS names to
test_asn_to_name_intandtest_asn_to_name_strto repair
test breakage caused by Cloudflare's AS name changing, and preventing breakage caused by
AS name changes in future.
2.8.0 - Refactoring, bug fixes, new loop_run function and more!
Tl;Dr; important changes
- Added asyncx functions:
loop_run,is_async_context,_awaitable_blacklisted - Added asyncx decorator
awaitable_class, and mixin classAwaitableMixin(mixin version of awaitable_class decorator) - Removed class
helpers.extras.git.Gitand replaced it with an alias toAsyncGitas@awaitable_classrendered the
wrapper class obsolete - Refactored some types from
commonmodule intotypes - Refactored tests and added some new tests for some of the added functions/classes
- Various refactoring and general cleanup
New Features / Additions
-
asyncx.loop_runis similar toasyncx.run_sync, but more flexible, and doesn't use the deprecatedasyncio.coroutine
function. It can be passed either a coroutine directly for execution, or if a function/method is passed,
(doesn't have to be async) then it can attempt to extract the coroutine by calling each layer until a coroutine
or non-callable is found.While there's no plan to remove
asynx.run_syncin the near future, it's strongly recommended to switch usages ofrun_sync
toloop_runbecause it's better at handling different forms of awaitable objects:-
Unlike
run_sync, loop_run can handle both async function references AND coroutines -
Unlike
run_sync, loop_run can unwrap coroutines / async function references that are wrapped in a normal
non-async function (e.g.@awaitablewrapper functions) -
Unlike
run_sync, loop_run can accept the optional_loopkeyword argument, allowing you to specify a custom asyncio
event loop if you desire. -
Unlike
run_sync, loop_run will cleanly execute non-async functions if they're encountered, and simply return
non-callable objects that were passed to it, instead of failing.
-
-
New function / class decorator
asyncx.awaitable_class- wraps a class and overrides__getattribute__to enable all async
methods to be called from non-async code. Similar toasyncx.awaitable, but affects all async methods in a class, and
doesn't require non-async wrapper functions to be written.-
If a non-async method or standard attribute is requested, then those are returned as normal without modification.
-
If an async method is called on the class, then it checks to see if there's a current AsyncIO context - if there is, it
simply returns the coroutine forawait'ing -
If there isn't an async context, it will use
loop_runto call the method synchronously using the
current event loop, and return the method's result synchronously.
-
-
New class
asyncx.AwaitableMixin- a mixin class which works the same asasyncx.awaitable_class, but as a mixin class
add to your class's inheritance, instead of a decorator. -
Created the file
CHANGELOG.md- note that it doesn't contain a full changelog yet, it only goes back as far as version 2.5
Changes / Updates
-
The wrapper class
helpers.extras.git.Githas been removed, asAsyncGitnow uses the much simpler@awaitable_class
decorator to enable synchronous usage of all async methods, instead of a sub-class with individually@awaitablewrapped
methods.To avoid breaking any existing code which relied on
extras.git.Git,Gitis now an alias forAsyncGit. No changes
needed to be made to the Git tests intests/test_extras.py, so this change isn't believed to cause code breakage. -
A large portion of the decorator
asyncx.awaitablehas been refactored into the smaller functions:_awaitable_blacklisted
andis_async_context. -
During the refactoring of
asyncx.awaitable, a bug was discovered in the blacklist scanning for sub-modules - this is now
fixed (note: blacklist scanning is refactored into_awaitable_blacklisted) -
asyncx.pynow has an__all__module attribute, allowing__init__to simply import*instead of having to list each
class/function etc. -
cache.asyncx.__init__-
Added a PyDoc comment at the start of the file, explaining the AsyncIO adapters and how to use them.
-
Added the attributes
HAS_ASYNC_REDIS,HAS_ASYNC_MEMORY, andHAS_ASYNC_MEMCACHEDto allow for easy availability
checking of async cache adapters. -
Lowered the
ImportErrorlog level for AsyncRedisCache and AsyncMemcachedCache fromlog.exceptiondown tolog.debug
-
-
Refactored various generic / template types (e.g.
T,K,CL) fromhelpers.commonintohelpers.types
Testing
-
Refactored
tests/test_general.pyinto a foldertests/general/ -
Refactored AsyncIO related tests from
tests/test_general.pyintotests/asyncx/test_async_common.py -
Added several new AsyncIO tests to
tests/asyncx/test_async_common.py, mainly aimed at the newasyncx.awaitable_class,
andasyncx.AwaitableMixin
2.7.0 - Async cache adapters + many new functions
New Features / Additions
-
privex.helpers.common- Added
extract_settingsfor extracting prefixed settings from modules, classes or dict's.
- Added
-
Created new
helpers.black_magicmodule for somewhat risky code that uses app introspectioncalling_function- Returns the name of the function which called your function/method.calling_module- Returns the name of the module which called your function/methodcaller_name- Get the fully qualified name of a caller in the formatsome.module.SomeClass.method
-
Created new
helpers.typesmodule for holding type aliases and new type definitions -
privex.helpers.decorators- Added
async_retrydecorator, which works similar toretry_on_error, but supports wrapping asyncio coroutines
- Added
-
privex.helpers.cache- Created new
asyncxsubmodule for AsyncIO cache adapters asyncx.base.AsyncCacheAdapteris a new base class for AsyncIO cache adapters, with all methods as corosasyncx.AsyncRedisCacheis a new AsyncIO cache adapter for Redisasyncx.AsyncMemoryCacheis a new AsyncIO cache adapter for in-memory caching (async version ofMemoryCache)asyncx.AsyncMemcachedCacheis a new AsyncIO cache adapter for MemcachedCacheAdapterhas a new methodget_or_set_async, which is an async method that supports
coroutines as a value, as well as standard callable's and plain values
- Created new
-
privex.helpers.plugin- New functions for organising __STORE by thread:
_get_threadstore,_set_threadstore,clean_threadstore - New functions for managing AsyncIO Redis (aioredis) instances
get_redis_async,close_redis_asyncetc. - New functions for managing AsyncIO Memcached (aiomcache) instances
get_memcached_async,close_memcached_asyncetc.
- New functions for organising __STORE by thread:
Changes / Updates
-
Added
aioredis,hiredis, andaiomcachetoextras/cache.txt -
async-propertyis now a core requirement, since it's used by a lot of async classes -
New settings
MEMCACHED_HOSTandMEMCACHED_PORTfor AsyncMemcachedCache -
New plugin status
HAS_ASYNC_REDISfor detecting ifaioredisis available -
privex.helpers.decoratorsretry_on_errhas been slightly cleaned upretry_on_errnow supports ignoring exceptions, so you can list exceptions that cause a retry, but shouldn't increase the retry count.retry_on_errnow supports the settinginstance_match, which changes how exceptions are compared. When enabled, it will
compare usingisinstance()instead of an exact type comparison.
-
privex.helpers.asyncxawaitabledecorator now detects when it's received a non-async function, and returns the result correctlyawaitablenow supports "blacklisting" functions/modules, to ensure when those functions/modules call an@awaitablefunction,
that they always get a synchronous result, not a coroutine.
-
privex.helpers.cacheCacheWrappernow uses@awaitablefor most methods, allowing AsyncIO cache adapters to be used without breaking existing
synchronous code which uses the cache API.CacheAdapternow has dummy__enter__and__exit__methods defined, allowing all synchronous cache adapters to be used
in awithstatement, regardless of whether they actually use context management.
-
privex.helpers.pluginget_redis,close_redis,reset_redisetc. now use the new thread store system to help ensure thread safety
by separating instances per thread.- Refactored
get_redis's connection opening intoconnect_redis, and now usesextract_settingsfor loading default settings
Testing
-
Added unit tests for
extract_settingstotests/test_general.py -
New folders
tests/asyncxandtests/cachefor containing flat test case modules using pytest-asyncio -
tests/asyncx/test_async_retry.pytests the new@async_retrydecorator -
tests/cache/test_async_memcached.pytests the newAsyncMemcachedCacheclass -
tests/cache/test_async_redis.pytests the newAsyncRedisCacheclass -
tests/cache/test_async_memory.pytests the newAsyncMemoryCacheclass
2.6.0 - `extras.git` + `asyncx.awaitable` + aobject
- Created
helpers.extras.gitmodule, which contains a git command wrapper that works with both sync and async functions- Primarily intended for the three methods:
get_current_commit,get_current_branch, andget_current_tag, which allows python applications and libraries
to identify what version they are, via git. - Includes various basic methods such as
init,checkout,branch,tag,status,logand others.
- Primarily intended for the three methods:
- Added new async helpers
aobjectallows sub-classes to haveasync __init__constructorsawaitablehelps create wrapper functions that allow async functions to work with sync code seamlessly
- Improved
byteifyandstringifywith None handling - Added new
SysCallErrorexception sniffiois now a required dependency - however it's very small and dependency free in itself (only about 30kb).- Added unit tests for the git module, including tests for both synchronous and asynchronous execution of the methods
- Re-generated some of the documentation
- Possibly other small changes
Final 2.5.0 release (PyPi published) - Converters, construct_dict, get_function_params and more!
2.5.0 - Converters, construct_dict, get_function_params
- Includes commit 12da829 which enables 2.5.0 to function fully on Python 3.6 and 3.7 (prior to this commit
some tests only worked on 3.8+)
commit 12da829
Date: Thu Dec 5 02:39:32 2019 +0000
Add local_tests.sh, fix get_function_params on older python
- Added `local_tests.sh` for running the unit tests on multiple python versions locally
- Added `OrderedDictObject` to collections module, since python versions before 3.8 cannot reverse a normal dict.
- Add unit tests for ordered dict object
- Adjusted `get_function_params` to use the new OrderedDictObject (fixes failing tests on older python versions)
New Features / Additions
privex.helpers.common- Added
get_function_params- which extracts and filters a function/method or class constructor's parameters, and
outputs them in a dictionary - Added
construct_dict, which allows you to either construct a class, or call a function using a dictionary of keyword arguments,
usingget_function_paramsto detect what arguments the class/function/method can take, including any parent classes, then
filtering out any keyword arguments which would otherwise be rejected and cause a TypeError. - Added
_filter_params, a private function used by the aforementioned functions to filter a dictionary or iterable of Parameter objects.
- Added
- New module
converters, containing functions/classes designed to convert/parse one type into anotherconvert_datetimeconverts both string date/time's as well as unix timestamps intodatetime.datetimeobjects usingdateutil.parserconvert_unixtime_datetimeconverts specifically UNIX epoch timestamps (can be string, int, float, Decimal etc.) intodatetime.datetimeobjects,
and is used byconvert_datetimeto handle unix timestamps.convert_bool_intconverts booleansTrue/Falseas well as string / int versions into integers 1 (true) and 0 (false)convert_int_boolis mostly an alias tois_true, but exists for convenience and semantics (if there's a convert_bool_int, why not a convert_int_bool?)
Changes / Updates
-
Shrank the rather large copyright notice in most modules down to the small copyright block, and instead of dumping the whole X11 / MIT License text in there,
the licence block simply statesLicense: X11 / MIT. This should make the docs a bit more readable. -
Added
python-dateutilto thePipfile -
For sanity reasons,
python-dateutilhas been added to theinstall_requires(meaning it's auto-installed when you install privex-helpers). The package is relatively
small and depends on justsix, weighing in around 500kb (python-dateutil = 468kb, six = 36kb).It may be removed and refactored into a setup.py extra at a later point, but for now it's small and commonly required enough that it can be a dependency.
-
Added
dateutilto the sphinx intersphinx mapping -
Possibly other small changes I forgot to include
Testing
- Added new test case
TestInspectFunctionsto test_general, which tests the newget_function_paramsandconstruct_dictfunctions. - Added new test module
test_converters.pywhich contains test cases for the new converters moduleTestConvertDatecovers date/time related converters such asconvert_datetimeandconvert_unixtime_datetimeTestConvertGeneralcovers other converters that don't fit into a specific category (or would otherwise be pointless to categorize)
2.3.0 - New `collections` module + refactoring
This is the final version of 2.3.0 (as published to PyPi) - merged from develop branch.
Includes the following extra commits since original release:
-
(commit 600cccd) Rename test_tuple to test_collections + add TestDictObject
-
(commit fa1f4db) Re-factored dictable_namedtuple and related functions for py3.6 / 3.7 compat
Minor updates
-
docs/source/conf.pynow setsPYTHON_PATHwhich helps reduce issues with Sphinx
finding the privex package folder -
Fleshed out
docs/source/examples.rstwithDictObjectanddictable_namedtupleexamples. -
Added documentation for
privex.helpers.collectionsandtests.test_collections -
Added
PipfileandPipfile.lockfor use withpipenvduring development
Major changes
-
Created module
privex.helpers.collections-
DictObject- Adictsub-class which allows keys to be read/written via
attributes (x.something) as well as standard item/key notation (x['something']) -
MockDictObj- Same asDictObject, but masquerades as the builtindict, potentially
allowing it to be used with certain code that expects the builtin dict type -
is_namedtuple- Boolean function which returnsTrueif all passed objects are named tuples -
dictable_namedtuple- An improved version of the nativecollections.namedtuple, which adds additional functionality
such as dict-like key/item access to fields, ability to cast directly to a dict, and ability to add new fields
dynamically to an existing instance. -
convert_dictable_namedtuple- Converts anamedtupletype class instance into adictable_namedtupleinstance -
subclass_dictable_namedtuple- Converts anamedtupletype/class into adictable_namedtupletype/class
-
-
Created unit tests for
is_namedtupleanddictable_namedtupleintests/test_collections.py
BREAKING CHANGES
-
Mockerhas been moved fromprivex.helpers.commonintoprivex.helpers.collections.
Code which imports viafrom privex.helpers.common import Mockerwill no longer work.
Code which importsMockerfrom the sharedprivex.helpersmodule (i.e.from privex.helpers import Mocker)
should be unaffected. -
Dictablehas been moved fromprivex.helpers.commonintoprivex.helpers.collections.
Code which imports viafrom privex.helpers.common import Dictablewill no longer work.
Code which importsDictablefrom the sharedprivex.helpersmodule (i.e.from privex.helpers import Dictable)
should be unaffected.