In: Articles

20 Aug 2014

CPANday is over – I had HUGE plans, well not for CPANday in particular, but for all of my CPAN contributions.

CPANday did however come very handy and was a magnificent initiative, but as always did not get as much done as I wanted to.

I made 7 maintenance releases, mostly getting up to speed with my distributions, which was previously stranded in migration.

- Business::DK::Phonenumber 0.07
- Business::DK::CPR 1.11
- Tie::Tools 1.07
- XML::Conf 0.05
- Business::Tax::VAT 1.04
- Business::DK::Postalcode 0.09
- Workflow 1.41

I made a single feature release of one of my newer distributions.

- Business::GL::Postalcode 0.03

I made two deletions.

- WWW::Nike::NikePlus::Public
- Business::OnlinePayment::Cashcow

The later very much spurred by the blog post by Book. There is no need to keep distributions on CPAN where the service they use is no longer available. The first was a scraper on the Nike+ community site, where a more well defined API has been developed. I do not think there is a Perl integration, but I do not really use Nike+ anymore after having shifted to Endomondo, so … Cashcow seems to have been discontinued. I created this distribution when working for a client, which was using Cashcow, but the company do not exist anymore and neither does the Cashcow owners it seems.

I would have loved to:

- Do a new release – I have several new releases planned (as part of a quest)
- Thank somebody – I need to buy NEILB a beer for his continued energy and contributions to the CPAN community
- Put my CPAN stuff on Github – Done
- Improve the POD (see also etc.) – I plan to go over POD on all of my modules, now that all of them are accessible on Github
- Close RTs – I have created a quest today to do exactly that
- Get coverage reports with Devel::Cover – I NEED coverage badges on all my distributions
- Address some test reports from CPAN testers – I have many of them as RTs, so they will be addressed
- Delete some distributions – Done and Done
- Blog about a CPAN module – there are SO many to choose from, but I have just started fooling around with Dist::Zilla, perhaps a blog post should be written :-)
- Give money to the Perl foundation – my employer does on a regular basis, but perhaps I should too

For me CPANday started a wave, it began slowly leading up to CPANday and now continuing with almost daily releases, cleaning, improving, fixing and most of all having a lot fun…

Thanks to all of the CPAN contributors, testers, users, Philippe Bruhat and especially Neil Bowers

CPAN deletions

In: Articles

11 Aug 2014

As I wrote in my post ‘Stranded in Migration’ I plan to delete some of my old distributions from CPAN, since they no longer hold any value. For me they hold value as projects from which I learned a lot, but to the open source, CPAN and Perl communities they no longer offer much value (if they ever did).

So I have deleted:

- Module::Template::Setup, an attempt at what Dist::Zilla or similar do a much better job at
- Games::Bingo::Bot, a complementary IRC bot for Games::Bingo, which should perhaps have been in the examples directory instead

The last distribution is pre-github, back when CPAN was the best way to display and distribute Perl code, today you have alternatives like Github if you just want to demonstrate a concept or want to prototype something. Today there is no need to push everything to CPAN, at the same time CPAN is a marvellous distribution channel and it is the best way to distribute working CPAN components if you want to share with the Perl community.

I have done regular cleaning of my CPAN distributions, always attempting to keep it down to the two latest releases, so a diff can be done, but clearing out stuff which is no longer of value, can only be encouraged, so we do not drown CPAN in old, unmaintained and obsolete distributions no longer holding any value.

Check if somebody depends on your distributions, alternatively ask around before deleting.

This is the first time I have deleted distributions completely, apart from when I mis-named a distribution and uploaded under a different name and it does feel good. I am not embarrassed by my first attempts at CPAN distributions, but it does feel good to delete them and focus on new distributions and maintenance and development of code, which holds more value to me and perhaps to members of the community.

Well everything is at BackPAN and for me at Github so I can look at my old code and see if I have evolved as a programmer :-)

jonasbn, Copenhagen

Update! 2014.08.13

I completely forgot I am also deleting Bundle::JONASBN, which has been replaced by Task::BeLike::JONASBN, an example of evolution of how to do things on CPAN.

These releases have been on my mind for a long time. I had the data resources to do it, but just could not find the time. Participating in the Questhub quest on releasing a new module every month was a boost and I scheduled the two new releases in this quest, but work and life in general caught up with me so they never got finalised.

During the summer holiday I finally found some time to get them out of the way, so I have released:

- Business::DK::Postalcode 0.08
- Business::GL::Postalcode 0.01
- Business::FO::Postalcode 0.01

Business::DK::Postalcode has been extended with a Mojolicious::Lite web application example and hereby some new methods improving the API to the data source.

GL and FO have had additional releases as 0.02 since after GLs release I needed to makes some changes introduced by requirements from FO, which is a subclass of GL.

All distributions are based on the same data source, which I split up by country code. DK only holds a procedural interface either to validate or extract the data, where GL and FO is implemented as object oriented offering the procedural interface as a wrapper.

The latter comes to a certain price, something I am working on fixing, since the performance penalty for this (can be observed with the test suite) is painful.

The projects have taught me a lot about Perl’s __DATA__ and all of the problems of supporting both a procedural and an OO interface and there is much to be learned still, but now the initial versions are out there and I am working on improvements and changes for the DK distribution so it can used in an object oriented manner too.

I am also working on additional example applications, since these really provide good insights on how to do things, it is really healthy to eat your own dog food.

So more releases will follow and hopefully I will be able to catch up with the quest, since I have more new modules lined up for finalising and release in the coming months and lets not forget about CPANday!!

jonasbn, Copenhagen

Spending a lot of time on Github, I observed that a lot of projects have cool badges on their pages indicating:

- build status
- coverage
- code climate

And so on…

I have been using Travis CI for my Github projects and it works like a charm. So when I fell over Dave Cross’ presentation and blog post on Travis CI and Github integration I had to read it case there was something useful I did not know and guess what there was.

Dave demonstrated how to get Travis CI and Perl on Github going, but also integrated with Coveralls and he showed how to get a coverage badge on your project.



And in combination with the Travis CI documentation describing how to get a build status badge



Okay, okay, two badges there most be more, so I did some googling and found CPAN badges, badges indicating the latest release to CPAN…



All examples are taken from my Github repository Business::DK::Postalcode and you know what it even works for MetaCPAN.

jonasbn, Copenhagen

My personal projects and code have lived a long life. I have been using RCS locally, CVS and SVN. My first public repositories was in my local Perl user group Copenhagen Perl Mongers, where we shared a central repository. It started out as CVS, but was migrated to SVN about the same time as I started uploading distributions to CPAN.

In parallel I also set up a few projects at SourceForge and later at Google Code, both using SVN (SourceForge started out as CVS for me, but migration had taken place at some point). Actually the most important project of mine there was Workflow, which was migrated from a closed SVN repository from the original author Chris Winters to SourceForge.

Anyway – for a long time I worked as a freelancer, dreaming of doing my own software instead of others. So I decided to go for a hosted solution with Versionshelf, I later changed to Atlassian, which at that time had nice product consisting of Jira, Confluence, Fisheye and Subversion (it was actually Fisheye, which let me to this, metadata on code has always intrigued me). All my new projects public and non-public got hosted here, but I still had a legacy stuck at the Copenhagen Perl Mongers Subversion server.

I got Google Code migrated to the Atlassian platform, but stayed with SourceForge because of the project organisation. The repos was a dead end, due to the structure, several attempts at getting the projects extracted properly was unsuccessful.

Then came Github a long and a completely new trend in VCS systems. Not always being a first mover I decided to stay put. I still wanted to migrate my old codebase, but could not find the time to sit down and do it.

Michael Schwern created Gitpan, which seemed like a nice solution, but it was based solely on the releases and a lot of history would be lost (to me a serious loss of meta data). There was even some nice blog posts on how to get the most out of Gitpan.

Workflow got migrated from SourceForge to Github, even though SourceForge hosted Git. I had experienced some issues with the administrative interfaces, which rendered the platform useless in a confusing redirect hell (this has been addressed now).

Atlassian then announced the end of life for their Subversion hosting and migration to Git (Bitbucket/Github) was possible. This was the push I needed and all of my code hosted with Atlassian got migrated, well almost all of it I still have some old customer projects still in a Subversion dump. But all of my open source projects got migrated to Github.

All my new projects now start up on Github. But still I looked at my legacy of distributions on CPAN, which I did not have active repositories for and it haunted me.

The in the summer of 2014 (this summer), I fell over Tony Bowden’s Business::Tax::VAT. I have used Business::Tax::VAT::Validation for some projects and never discovered this module, so I checked it out and it seemed that it had not had any releases in a long time and 3 our of 4 RTs was low-hanging fruit, but no Git repo.

So I mailed Tony Bowden and got COMAINT on PAUSE, we wrote back and forth about Github and we investigated the Gitpan version. Luckily the latest version on CPAN was aligned with Gitpan, so I could pick up from there. Fork, Fix and Free. Got the 3 tickets closed and shipped a release, I had to do additional release when it got picked up by the CPAN testers, but that was nothing when it was hosted on Github.

This struck me as a marvellous situation, so I went back to Gitpan and compared it’s versions of my legacy distributions which was not on Github and I was able to create forks of all of them. Yes, this would mean loss of history, but again I would much rather be able to code and maintain, than not being able to do anything.

So now all of my open source Perl projects are on Gitpan and I am a very happy camper. Maintenance releases will start to go out for most of the legacy and some will be deleted (completely) from CPAN, since they are of no value, but they will still be on BackPAN, Gitpan and for me on Github.

My legacy is under control and I am no longer stranded in migration.

jonasbn, Copenhagen

From the MOTIVATION section in the POD of this new policy:

I once read an article which compared programming languages to natural languages. Programming languages in themselves are not large as such, but if you also regard the APIs, data structures and components a computer programmer use on a daily basis, the amount is enormous.

Where I work We try to keep a more simple code base, the complexity is in our business and that is our primary problem area, so it should not be difficult to understand the code used to model this complexity.

So sometimes it is necessary to make a decision on what should be allowed in our code base and what should not. This policy aims to support this coding standard.

This sounds fairly unproblematic and peaceful, but there is a more sinister motivation behind the implementation as well.

After long debugging sessions at the most inconvenient times involving a small set of modules, which causes me too many problems – I decided to write this policy.

Over the cause of time and working in a growing team, we have a constantly growing code base and many takes on how to accomplish things and solving problems. Constantly our code base is breaking and new bugs are introduced and this is all okay and a pretty natural part of software development.

Developers are great!

- They add value
- They add code
- They fix stuff
- They build stuff


- They introduce bugs
- They implement security holes
- They add code
- They break stuff

So sometimes that have to be regulated.

We use peer reviews, not to the extent we should, but we do try and aim try to have this is a part of our SDLC (Software Development Life Cycle). Sometimes we tend to discuss the somethings over and over and perhaps at some point we decide to adjust our coding policy to accommodate the outcome.

My thesis is a that we should use Perl::Critic and Perl::Tidy to enforce our coding standard to the extent possible so peer reviews can focus and can be provide maximum value and we can discuss business, value, security and discover new anti-patterns/patterns, instead of discussing old hat.

So when a certain issue has been observed on more that one occasion, write a policy to enforce a regulation against to address it.

This policy can help you to enforce a regulation when you want to prohibit use of certain modules or even when you want to recommend alternatives.

So if you want to specify a list of blacklisted modules:

modules = Try::Tiny, Contextual::Return, IDNA::Punycode

And if you want to hint at recommendations for use:

modules = Try::Tiny => TryCatch, Contextual::Return, IDNA::Punycode => Net::IDN::Encode

Please note that this is the first shot at the policy, feedback and suggestions most welcome (Github).

Happy regulating,

jonasbn, Copenhagen

Following up on the comments to my blog post on CPAN::Changes and CPAN::Changes::Spec, I created a fork of the distribution on Github and implemented a first shot for the author to evaluate. I sent the pull request yesterday, so now it will be interesting see whether it will be found useful at all.

I did a lot of thinking before starting the actual coding and I was not quite satisfied with the vocabulary I was using to describe the concept. Originally I referred to the concept as impact pointer, but it is simply misleading and not particularly descriptive. So when it occurred to me that the concept was actually hints on how the reader should view the changes and release described it came to me that the obvious name should be “update hint”.

Hints are everywhere and is the term is highly popular these days. Hints are less intrusive and in this case a much better description.

Here is an example lifted from the POD.

0.03 2010−08−01 − update recommended

− Fixed serious bug in bar method

0.02 2009−07−17 − update not required

− Added more foo() tests

0.01 2009−07−16

− Initial release

I decided for two values of the hint:

        - update recommended
        - update not required

The first for for releases, which address serious issues/bugs like security fixes, memory leaks etc. the second for releases which are housekeeping releases, updates to tests, documentation, build scripts etc.

As you can see there is no hint for the initial release. I do not want to impose my proposal on the existing specification as such and I well let it be up to the maintainer to decide whether it should be optional and what the actual values should be, my proposal works, but it just a proof of concept and in my opinion it is a nice concept I hope will be adopted.

Please feel free to evaluate my proposal for update hints in the CPAN::Changes::Spec and let me know what you think.

jonasbn, Copenhagen/Denmark

I have been using the Sublime Text 2 editor for some time now. Editors are a funny thing and over the years I have used quite a few different ones: pico, vi, vim, jEdit, BBEdit, TextMate, Komodo IDE and now Sublime Text. I like to have an armory of editors in my toolbox for different kinds of things. An editor for basic fast (right now) text editing, one for longer coding sessions and one for project development with several files of different types.

For a long time I was using a combination of Vim, BBEdit/TextMate and Komodo IDE for the different coding assignments under the circumstances I mentioned above. I later exchanged BBEdit for TextMate at some point and when I got CLI integration running for TextMate I slowly stopped using Vim. I still use the Komodo IDE, since the graphical debugger is a magnificent tool, one I simply cannot live without, but Komodo has longer startup time and is not well suited for short tasks unfortunately.

Hearing all the (b|f)uzz about Sublime Text intrigued me and made me want to check it out. I have read quite a few blog posts and I have watched several video tutorials – and they all say that when you start with Sublime Text you will not want to go back – yeah right!

I must however admit that I am impressed, the editor is flexible, easy to use, incredibly fast and responsive and it is really, really, really easy to customize.

Editors are the primary tool of most developers. Often we spend more time in editors editing code, than we actually do compiling or translating the actual source code. There are many opinions on editors, most developers have a favorite and in addition an opinion on the other developers favorite. Some are quite religious about their editor and mocking or talking about the other editors is not uncommon and most of you already know the funny diagram depicting learning curves for the most “popular” editors.


The depiction is funny, but as it is with most satiric fun, it comes with a grain of truth. I am not going to dig more into the above visualization since I will not attempt to visualize the learning curve of Sublime Text and because my opinion would be subjective and not as funny as the above examples, which I guess are all created with great love/hate to the editors mentioned. I think I can take liberty of writing love/hate since it is with most things you love you really hate when they let you down.

Getting back to Sublime Text I can only say that the editor is growing on me and I do not love it as such and it was not love at first sight since I actually just thought that it was just another editor, but Sublime Text continues to impress me and I feel like it gets better the more I use it and really feels like the editor for me. I do spend time coding, not as much as I would like to, since I am also using the Microsoft Word (editor) for a large part of my work, but luckily I get to do some coding and if not at work then at least when I am not at work.

When watching some Youtube tutorials I fell over the concept of Zen Coding, this was the idea of being able to write code with as few key stroke as possible (not like Perl golf), but getting productivity and speed up utilizing and maximizing you and your editors coding/typing capabilities. The demo for Sublime Text for HTML markup was really impressive and it got me thinking.

Sublime Text has a nice Perl integration, syntax highlighting, it builtin auto-completion can get you a long way and you can install plugins for integration with Perltidy and the plugin SublimeCodeIntel will extend this even further.

Inspired by the Zen Coding demonstration I thought CPAN has a log of APIs, so what would be the most useful ones to play around with for creating cool snippets for speeding up my Perl coding and then it occurred to me, that the modules and APIs I actually use the most are for implementing unit tests using Test::More and Test::Class, I do this across all my distributions and projects and both at home and at work.

So here is my first shot at snippets for Test::More and Test::Class available on Github for you to use with Sublime Text or fork you can fork them to suit your own needs. I am working on getting them made available via SublimeTexts Package control, which requires a pull request to a central repository of metadata, where I am still waiting for approval.

If you are in a situation where you feel like trying out a new editor, checkout Sublime Text, I have only tried version 2 and there is a version 3 on the way, I will not say that “it will not make you want to go back”, since my history of editors is long and proves the opposite and I expect it will continue to evolve, but I can promise you that it will be both fun and inspiring as you discover the nifty features and niceties which gives the sublime in Sublime Text.

Happy coding,

jonasbn, Copenhagen/Denmark

Today I have uploaded a new release of my Perl::Critic::logicLAB, it lists the two new policies I mentioned on earlier occasions in my blog.

- Perl::Critic::Policy::logicLAB::RequireParamsValidate
- Perl::Critic::Policy::logicLAB::RequirePackageNamePattern

Both released are released and maintained as separate distributions and Perl::Critic::logicLAB acts as a collection (Task::). RequirePackageNamePattern 0.01 was uploaded to CPAN about a month ago and RequireParamsValidate 0.01 was uploaded today together with Perl::Critic:.logicLAB 0.08.

I could have uploaded RequireParamsValidate earlier, but I decided to participate in the Questhub challenge of releasing a new CPAN distribution for every month for 2014 so I decided to stretch the releases for two months. Apparently I forgot to blog about the releases as nicely pointed out by the master questhubber and overall CPAN magician Neil Bowers, so here it is the public announcement of the two releases for January and February.

Their basic details have been fleshed out earlier so I am not going to go into details with the policies as such, but I do however want to address an issue that was raised in conjunction with the challenge on Questhub and that was the flooding of CPAN of new releases bringing no actual value (as I read it). This brings me back to my own contributions and the two mentioned policies.

It is really hard to come up with CPAN distributions that satisfy a greater audience, I for one do by no means satisfy needs other than my own, I would love to, but lets be honest, that is hard – I will get back to that later.

The same problem applies to Perl::Critic policies, coming up with original ones are not so easy as it sounds. But I write policies that my own scratch my own itch and I write policies to get accustomed to working with policies. And just as policies, Perl distributions serve many purposes and some are for getting your head around a specific problem area or improving your own workflow for working with a certain problem area.

A very positive thing in all this apart from the obvious reasons like learning something new, sharing your knowledge and sharing your techniques as open source benefits others – yes it might be annoying and it might be hard to find exactly the best suited module for addressing a certain problem, but my experience with CPAN tells me that the community part of CPAN will take care of that and you can always use trusted sources like the Intarwebs to find your way – what I really mean is that you can always go to you local Perl mongers group, IRC or places like StackOverflow to get guidance and pointers in the right direction and if all is lost – roll you own.

I have several distributions on CPAN, which are dead-ends, they should perhaps be deleted, they will persist on BackPAN, but I just have not gotten “around to it”. These distributions served a purpose at one time, I made errors and mistakes, I learned lessons and I improved as a Perl programmer, CPAN distribution maintainer and Open Source contributor.

Most of us can agree that trial and error is one of the best learning practices and practicing with CPAN distributions might be overkill for silly and personal experiments, but for a long time and still to some extent CPAN is the main repository for Perl code, yes we have Github and cpanm and we can do things differently, but CPAN is just a part of larger ecosystem and the questions you most hear often when you interact with the Perl community when people outline an idea, a concept or a project are:

  1. It is on CPAN?
  2. When will it be on CPAN?
  3. Will it be on CPAN?

(the order of the questions should be random, but for the sake of the beauty of the poetry in the questions the order here is arranged).

So CPAN is important for marketing and distributing your work and getting all the benefits of the community driven tool-chain. And to get back to a previous blog post on Perl and its role in the overall developer community, where it is often regarded as dead, every little contribution, every new distribution which is uploaded or updated on CPAN matters. Perl is alive because of CPAN (*1), because here everybody can play along and it is not so hard and it should not be hard to contribute. I recently migrated my Workflow distribution from SourceForge to Github, simply to easy the process of contributing and SourceForge and Github are important, but CPAN is the distribution channel.

And if you read the blog post I mentioned, the other languages to which Perl is compared their repositories are larger and they are growing and have outgrown CPAN and they are generating buzz, so there is absolutely no need to shut the castle gates and go all ivory over Perl – yes there will be lots of useless crap uploaded and I for one will be one of the contributors in to the (cr)App:: namespace (*2), but natural selection will sort it out and the best distributions will survive, long after there authors have stopped maintaining them, simply because of the community – and CPAN is the community, so when you contribute to CPAN you contribute the community.

It is hard to contribute with original stuff, it is hard to come up with original ideas and implementations that will rock the community. But everybody who has just touched product development, entrepreneurship know so. So until you ship that distribution, which will rock CPAN and get the Perl community all buzzing, because “you can get it on CPAN today” – code, share and learn.

I plan to upload 10 more new distributions this year, I have about 5 up my sleeve and I will run out of ideas just after summer with the current plan, but I am sure that using CPAN and interacting with the Perl community will give me additional ideas for contributions and this gives me a slight chance that I might be able to complete the challenge for 2014.

jonasbn, Copenhagen/Denmark

*1 Not solely, I do not want to forget all the people contributing to the Perl core, they are indeed keeping Perl alive, but in this context they will be mentioned in a footnote – sorry.

*2 This is just a pun, like “Captain of the USS Make-shit-up”, the App:: namespace is a fine a well respected namespace of which I am a happy user – thanks to its contributors

I have just released Task::Jenkins 0.05 to CPAN (meta).

This is a feature release and it now included Devel::Cover::Report::Clover which is a report formatter for Devel::Cover, which can generate Clover reports consumable Devel::Cover reports in Jenkins using the Clover Plugin.

This does as such not replace the HTML Publisher Plugin integration I normally recommend but it does provide the Jenkins use with a graphical overview of the coverage metrics.

An example:

The configuration of the plugin is pretty basic:


We specify where we want the report to be and in our actually integration test step we add the following:

#create Devel::Cover report
./Build testcover

#create clover report from Devel::Cover using #Devel::Cover::Report::Clover
./cover -report clover -outputdir clover

In addition I generate the HTML reports and these are then accessible via clicking the graphical coverage report (please see my Wiki page on Continuous Integration for Perl using Jenkins).

#create html report from Devel::Cover::Report::Html
./cover -report html -outputdir clover && \
mv clover/coverage.html clover/index.html

This reports already exist since they are generated by Devel::Cover by default so perhaps a copy of these from cover_db can be done, but this was the first shot – or is strikes me I could just tell the clover report generation to output to
cover_db/ – this has to be tried out.

The rename of coverage.html to index.html is however unavoidable AFAIK to support the integration with the plugin.

This is really swell, BUT WAIT there is more…

This next part is not currently a part of Task::Jenkins, but I do mention it in the POD distributed with Task::Jenkins from this release and it might go in in the future. It was pointed out to be that a Jenkins plugin exists to visualize Perl::Critic reports, it is called Violations (thanks mil for the tips on plugins).

It is somewhat more tricky to set up. Lets start with the configuration:


You start by pointing to perlcritic.txt, this file should contain output from a Perl::Critic run.

The plugin simply parses output from Perl::Critic. So you have to add a step to generate this file, which should contain something a long the lines of this:

./perlcritic –brutal –verbose 5 –profile \
t/perlcriticrc lib t > perlcritic.txt

I run with the highest severity since I just want a report of everything. I point to the perlcritic resource file following the distribution (also under version control), but I overwrite severity using –brutal and output format using the verbosity flag.

It is quite important to output in format 4 or 5 since only these are supported by the plugin. I normally prefer format 8 since it makes it easy to copy-paste the policy name into a perlcriticrc file.

With format five you get also the filenames and you redirect it into the text file.
Then you will get the following graph for you build.


And when you click the graph you get the following detailed view:


You can see violations, violations by severity, trends and by clicking the filenames you get even more in-depth information.


My Wiki page on Continuous Integration for Perl using Jenkins will be updated soon with all of these findings and other tips and goodies.

Please let me know if you experience issues or have other tips I could benefit from.

Continued happy integration!

jonasbn, logicLAB

About this blog

This blog acts as a channel for communicating logicLAB’s open source activities. Announcements on open source initiatives, involvements and releases of open source distributions of software products, projects and applications.


  • jonasbn: Book wrote a more elaborate piece on CPAN deletions, which is worth mentioning: http://blogs.perl [...]
  • Neil Bowers: It would be good to hear your thoughts on supporting both an OO and procedural interface: what was t [...]
  • J: I'm experiencing the same issue as Petar. Anytime I click on any file, ‘No violations found’. N [...]
  • Petar: Nevermind that, I solved it with: perlcritic --brutal --verbose 5 lib t > perlcritic.txt || EX [...]
  • Petar: Hi Jonas, I tried adding perlcritic command as Windows batch command, but since my code has viola [...]


August 2014
« Apr